简体   繁体   中英

Connecting One Model to Multiple ViewModels in MVVM WPF

I am trying to accomplish a navigation bar and a content screen in.NetFramework WPF application. My goal is to implement MVVM pattern. The main objective is when I hit Users button in navigation bar, I want my Body page to render "Users" text. And when I press Actions button, body page must render "Actions" text. Navigation buttons are "Users" and "Actions". I have 3 View pages that are OperationPage, Navbar and Body. OperationPage is using Navbar and Body XAML to create view. The grid code is as following:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="20*" />
        <RowDefinition Height="80*" />
    </Grid.RowDefinitions>
    <Grid Grid.Row="0">
        <local:Navbar/>
    </Grid>
    <Grid Grid.Row="1">
        <local:Body/>
    </Grid>
</Grid>

Navbar grid is as follows:

<UserControl.DataContext>
    <vm:NavbarViewModel/>
</UserControl.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50*" />
        <RowDefinition Height="25*" />
        <RowDefinition Height="25*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="0">
        <TextBlock Text="{Binding Path=CurrentPage}" FontSize="30"/>
    </Grid>
    <Grid Grid.Row="1">
        <Button Content="Users" Width="75"/>
    </Grid>
    <Grid Grid.Row="2">
        <Button Content="Actions" Width="75"/>
    </Grid>
</Grid>

And Finally Body grid is as following:

<Grid>
    <TextBlock Text="{Binding Path=CurrentPage}" FontSize="30"></TextBlock>
</Grid>

I have created a ViewModel classes for both Navigation and Body that implements INotifyPropertyChanged. I can change the text from these classes. One of them is as following for navigation bar.

    class NavbarViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyChange(string changedVar) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(changedVar));

    private string _currentPage = "Navbar Data";
    public string CurrentPage
    {
        get { return _currentPage; }
        set
        {
            _currentPage = value;
            NotifyChange("CurrentPage");
        }
    }


}

But I am stuck with connecting these two classes to a Singleton ViewState class. Should I again implement two-way binding with INotifyPropertyChanged to my model class or Should I follow another way? I tried implementing the INotifyPropertyChanged class again in my Model class but I could'not find a way to create connection between the ViewModel class and model.

You might solve this in a couple of ways . The first way is to strongly-couple your ViewModels, like this.

OperationPage View

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20*" />
            <RowDefinition Height="80*" />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <local:Navbar DataContext="{Binding NavbarViewModel}"/>
        </Grid>
        <Grid Grid.Row="1">
            <local:Body DataContext="{Binding BodyViewModel}"/>
        </Grid>
    </Grid>

Then implements the OperationPageViewModel . This ViewModel should implement the INotifyPropertyChanged interface and it must have the 2 properties named NavbarViewModel and BodyViewModel of types NavbarViewModel and BodyViewModel respectively.

You might need to add to NavbarViewModel 2 events binded to Users' button clicked and Groups' button clicked in order to expose them outside and OperationPageViewModel should monitor those events (it has the instance of NavbarViewModel) then for example set CurrentPage property of BodyViewModel accordingly on user's button click.

Another solution might be to decouple ViewModels.

This solution get you better code maintenance and also let you code less than the first solution.

You need to use Message Broker design pattern https://en.wikipedia.org/wiki/Message_broker you can implement your own Message Broker or simply use one of any MVVM Toolkit libraries that already implement it. Most of the existing MVVM Toolkits have their own Message Broker implementation. So no need to re-invent the whell.

For example, the MVVM Light Toolkit Message Broker is explained here: https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/june/mvvm-the-mvvm-light-messenger-in-depth#using-messages

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM