как изменить значение текстового блока вне пользовательского элемента управления, если текстовый блок находится в другом окне

#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 пользовательских элементов управления и просто разрешайте им привязываться к основной модели представления. Есть ваше общение.