user3175654
user3175654

Reputation: 11

Sharing the ViewModel amongst multiple Views

I certainly hope that this question is easy to answer but it's been days and I haven't figured out how to share data between UserControls.

The page below has two tabs and their sources are referenced. It also has a button labeled Start that accesses a command within the ViewModel.

The problem I'm having is the data is actually within the tabs. I set them to use the same ViewModel and they each create their own instance of the ViewModel so the data is never present to the Start button. I hope that makes since.

It's a rather simple program and I don't really see the need to have 3 separate ViewModels that only contain single elements but perhaps that's what I need to do. All in all, I still need to gather all of the data from everything and submit it to an outside entity when I hit that start button.

I apologize if this is a question that's been asked before but I'm relatively new to C# so I'm not entirely certain what I'm asking for. Thanks in advance!

<UserControl
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:mui="http://firstfloorsoftware.com/ModernUI"
             x:Class="DeployWiz.Pages.Config"
             mc:Ignorable="d" 
             xmlns:local="clr-namespace:DeployWiz.ViewModel"
             d:DesignHeight="356.978" d:DesignWidth="333.582">
    <Grid Style="{StaticResource ContentRoot}" Margin="16,28,16,5" >
        <Grid.DataContext>
            <local:ComputerViewModel/>
        </Grid.DataContext>
        <mui:ModernTab x:Name="tabList" Layout="List" SelectedSource="/Views/ComputerView.xaml" Margin="0,0,0,40">
            <mui:ModernTab.Links>
                <mui:Link DisplayName="Settings" Source="/Views/ComputerView.xaml" />
                <mui:Link DisplayName="Applications" Source="/Views/ApplicationView.xaml" /> 
            </mui:ModernTab.Links>
        </mui:ModernTab>
        <Button Content="Start" HorizontalAlignment="Center" Margin="0,0,0,5" VerticalAlignment="Bottom" Width="75" Command="{Binding Path=StartTask}"/>
    </Grid>
</UserControl>

Upvotes: 1

Views: 3258

Answers (3)

akjoshi
akjoshi

Reputation: 15772

As per my understanding I would implement it something like this -

MainWindowViewModel -

  • Having an observable collection of ComputerViewModel's.
  • Having a StartTask command, which will use the items in collection to commit changes etc. i.e. will have data of all tabs.

MainWindow -

  • Window which is responsible for creating tabs.
  • Creates Tabs dynamically using collection of ComputerViewModel's in MainWindowViewModel (can use DataTemplate etc.)
  • Each tab will use the UserControl you have (except the Start button), UserControl will stil have the ComputerViewModel as it's DataContext.
  • Have a Start button binding to StartTask command in MainWindowViewModel.

ComputerViewModel -

  • Doesn't require StartTask command (unless it is supposed to perform some ComputerViewModel specific task, in that case it should be renamed to something appropriate)

Benefits of this approach -

  • Tabs creation will be dynamic and will automatically work in case you need to add more tabs (computers)
  • You can easily upgrade MainWindowViewModel to support more functionality like Remove/Add tabs etc.
  • Easy to maintain as you don't need to handle passing data between tabs etc.

Let me know if you have any questions or something is not clear.

Upvotes: 1

har07
har07

Reputation: 89285

I think you need to be consistent. If you decided to distribute responsibility of handling data in each View/UserControl to different ViewModels then the same way need to be applied when passing the data to outside entity. Each ViewModels responsible to pass the data. Having a button outside those controls is not an issue. There is Mediator Pattern as a best practice to communicate between viewmodels. That way you can send message to ViewModels in each control from the button's viewmodel. Upon receiving the message from button, you can instruct them to pass the data to outside entity.

"communication between viewmodels wpf" is the keyword to search for your problem here. If you use MVVM Light, sending message and subscribing to a message is as simple as shown here. Other major MVVM framework like Calliburn and Prism also has it. Otherwise you can search for simple implementation of Mediator pattern (I guess many people has implemented it, you can use their codes).

Upvotes: 0

Jim
Jim

Reputation: 2984

Are u using any MVVM framework ?

It depends, there are different approaches, it's common that multiple views access one viewmodel.

One, if already instantiated

this.DataContext = ViewModelName(); (datacontext binding in the backend code ofc)

MVVM Light toolkit will do this for u within the ViewModel Locator, i believe so

Also u can read this posts answer to make static viewmodels in the App.xaml.cs file singleton One ViewModel and multiple views

Upvotes: 1

Related Questions