#c# #wpf #xaml #mvvm
Вопрос:
Моя главная цель здесь-изменить текст боковой панели после ОБНОВЛЕНИЯ пользователем username
.
Мой текст на боковой панели (тот, который отображает имя пользователя) размещен в моем MainWindow.xaml
:
<Window //namespaces and properties here
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent">
<Border Background="#222529"
CornerRadius="20">
<Grid>
<!--Removed some UI elements for simplicity-->
<!--I have a sidebar menu here which I can navigate-->
<!--Username (The text that I want to change after updating User's username-->
<TextBlock Text="{Binding CurrentUserAccount.Username}" />
<!--Where the views are going to be displayed-->
<ContentControl Content="{Binding CurrentView}" />
</Grid>
</Border>
</Window>
Это мое UserAccountView.xaml
, и я обновляю данные пользователя здесь
<UserControl //namespaces and properties
Background="Transparent">
<Grid HorizontalAlignment="Center">
<!--Removed some UI elements for simplicity-->
<!--Username Textbox-->
<TextBox Style="{StaticResource TextBoxTheme}"
Text="{Binding CurrentUserAccount.Username}"/>
<!--Password Textbox-->
<usercontrols:BindablePasswordBox Style="{StaticResource BindablePasswordBoxTheme}"
Password="{Binding CurrentUserAccount.Password}" />
<!--Update Profile Button-->
<Button Content="Update Profile"
Style="{StaticResource GeneralButtonTheme}"
Command="{Binding UpdateCommand}" />
<!--Check current user details (just a temporary button to check user details)-->
<Button Content="Check details"
Style="{StaticResource GeneralButtonTheme}"
Command="{Binding CheckDetailsCommand}" />
</Grid>
</Grid>
</UserControl>
Я знаю, что данные пользователя указаны Updated
из-за временной кнопки, которая может проверять данные пользователя (и, конечно, данные пользователя меняются, когда я снова вхожу в систему). Вот как я выполняю проверку:
MessageBox.Show($"Id: {CurrentUserAccount.Id}
nUsername: {CurrentUserAccount.Username}
nPassword: {CurrentUserAccount.Password}
nDate Created: {CurrentUserAccount.DateCreated}");
Вот как я перемещаюсь по своему меню (если это имеет отношение к вопросу)
class MainWindowViewModel : BaseViewModel
{
public ICommand DashboardViewCommand { get; }
public ICommand ProfileViewCommand { get; }
// and other commands for each View
public DashboardViewModel DashboardVM { get; set; }
public UserAccountViewModel ProfileVM { get; set; }
// and other ViewModels
public object CurrentView { get; set; }
public UserAccount CurrentUserAccount { get; set; }
public MainWindowViewModel(UserAccount currentUserAccount)
{
CurrentUserAccount = currentUserAccount;
DashboardVM = new DashboardViewModel();
ProfileVM = new UserAccountViewModel(currentUserAccount.Username);
CurrentView = DashboardVM;
DashboardViewCommand = new NavigationCommand(o => { CurrentView = DashboardVM; });
ProfileViewCommand = new NavigationCommand(o => { CurrentView = ProfileVM; });
}
}
The DataTemplate
of my Views
(in App.xaml):
<Application.Resources>
<ResourceDictionary>
<!--Binding the View to its ViewModel-->
<!--Dashboard-->
<DataTemplate DataType="{x:Type viewModel:DashboardViewModel}">
<view:DashboardView />
</DataTemplate>
<!--User Account (if I share ViewModels and remove this, then I can't see my View now)-->
<DataTemplate DataType="{x:Type viewModel:UserAccountViewModel}">
<view:UserAccountView />
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
How is it possible to change the value of an element from a Window
if I am «changing» if from a ViewModel
(that is is a ContentControl
)?
Я должен задать этот вопрос, так как я не нашел ничего подобного в этой проблеме, и я действительно не знаю, какие «ключевые слова» мне следует искать, так как я впервые создаю приложение WPF.
РЕДАКТИРОВАТЬ: Я уже решил эту проблему благодаря комментарию @Clemens (который дал мне представление о том, что искать), я смог поделиться моделями просмотра для моей главной страницы и моего пользовательского аккаунта, удалив DataContext
для моего пользовательского аккаунта и установив DataContext
на UserControl
уровне:
<!--this is what my UserAccountView looks like-->
<UserControl <!--properties and namespaces-->
DataContext="{Binding Path=DataContext,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
ЕЩЕ ОДНО РЕДАКТИРОВАНИЕ 😇:
Я нашел другой способ сделать это, разделив модель MainWindowViewModel и модель UserAccountViewModel, чтобы модель MainWindowViewModel (где остается мой код, связанный с учетной записью пользователя, из-за наличия «общей» модели просмотра) не запутывалась.
Вот как сейчас выглядит моя модель MainWindowViewModel
class MainWindowViewModel : BaseViewModel
{
public ICommand DashboardViewCommand { get; }
public ICommand ProfileViewCommand { get; }
public DashboardViewModel DashboardVM { get; set; }
public UserAccountViewModel ProfileVM { get; set; }
public object CurrentView { get; set; }
public MainWindowViewModel(UserAccount currentUserAccount)
{
DashboardVM = new DashboardViewModel();
//this is the change (the UserAccountViewModel now accepts an instance of the useraccount,
//instead of the user's name, so when I change a property of that instance,
//it will be reflected to the binding text of the sidebar as well)
ProfileVM = new UserAccountViewModel(currentUserAccount);
CurrentView = DashboardVM;
DashboardViewCommand = new NavigationCommand(o => { CurrentView = DashboardVM; });
ProfileViewCommand = new NavigationCommand(o => { CurrentView = ProfileVM; });
}
}
Теперь весь код, связанный с UserAccount
этим, будет выполнен в UserAccountViewModel
, а не в MainWindowViewModel
.
Комментарии:
1. Как обычно, окно и пользовательский элемент управления должны использовать общую модель представления. Пользовательский элемент управления никогда не должен иметь свою собственную модель частного представления.
2. ждать… все мои «Представления» имеют свои собственные модели представлений, и все мои «Представления» являются пользовательским управлением. значит ли это, что вся моя логика будет в одной большой модели представления?
3. Или в моделях дочерних представлений модели основного представления. Частные модели представления элементов управления не знают друг друга и, следовательно, не могут обмениваться данными.
4. Ждать. Мне жаль. но я не понимаю смысла того, что вы сказали. Я только начинаю заниматься wpf и mvvm, и я все еще не знаю всех тонкостей, и я нахожу ваш ответ сбивающим с толку.
5. Что ж, начните с одного класса модели представления и одного его экземпляра, назначенного тексту данных элемента верхнего уровня, т. е. Окну. Не устанавливайте явно DataContext пользовательских элементов управления и просто разрешайте им привязываться к основной модели представления. Есть ваше общение.