fgth
fgth

Reputation: 21

Can't use data from MainViewModel in another ViewModel

I have a Problem with MVVM and two Views and corresponding ViewModels.

I have a MainViewModel and SettingsViewModel.

The MainViewModel executes on program start reading settings from an xml file. If I click on a Settings Button in the main view the SettingsView will be open with the binding SettingsViewModel and should fill the forms with Data. But the Problem is how can I get the Data from the MainViewModel to the SettingsViewModel?.

In the SettingViewModel I don't have a reference of the MainViewModel. How can I get this?

My first idea was to set the Data over the constructor but I can't use the constructor for this because I get the instances of the View with DataTemplate in the App.xaml:

        <DataTemplate DataType="{x:Type viewmodels:SettingsViewModel}">
          <views:SettingsView/>
        </DataTemplate>

My second idea was to solve it with Events. But that didn't work either because I don't get the reference of the SettingsViewModel in the MainViewModel.

This is my first project using MVVM pattern. Maybe it's an understanding problem of mine.

I'm trying to solve this problem since one week and I'm very desperate now.

I created a sample Project on Github for better understanding: https://github.com/fgth/Example

Please help me - Thank you.

Upvotes: 0

Views: 303

Answers (1)

Funk
Funk

Reputation: 11201

This is my first project using MVVM pattern. Maybe it's an understanding problem of mine.

Your MVVM layering is fine.

  • Model: Settings
  • ViewModel: SettingsViewModel
  • View: SettingsView

Storing / using the Settings instance on the parent MainViewModel also makes sense.

Your problem is more a static vs instance misunderstanding.

In SettingsView you define your SettingsViewModel as a static resource. Meaning its default constructor will be called every time a SettingsView is resolved.

<UserControl x:Class="Example.Views.SettingsView"
             ...
             >
    <UserControl.Resources>
        <ResourceDictionary>
            <vms:SettingsViewModel x:Key="settingsvm"/>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel DataContext="{StaticResource settingsvm}">
        ...
    </StackPanel>
</UserControl>

Given you create a new Settings instance in the SettingsViewModel constructor, you'll always end up with a blank slate.

public SettingsViewModel()
{
    Mysettings = new Settings();
    ...
}

It would be better to pass the Settings instance from the MainViewModel to the SettingsViewModel on each request.

ActualPage = new SettingsViewModel(mysettings);

The updated constructor using Dependency Injection.

public SettingsViewModel(Settings settings)
{
    Mysettings = settings;
    ...
}

It wasn't the DataTemplate flow that was complaining about the constructor, it just matches types. However, the static resource did require a parameterless constructor, but again we don't need / want that functionality. After updating the SettingsView everything should work as expected.

<UserControl x:Class="Example.Views.SettingsView"
             ...
             >
    <StackPanel>
        <Label Margin="10" Content="TestView" HorizontalAlignment= "Center" FontSize="20"/>
        <Label Margin="10" Content="TextBox" HorizontalAlignment= "Center"/>
        <TextBox Width="200" Margin="0" Text="{Binding Mysettings.TextOfSetting}"/>
    </StackPanel>
</UserControl>

Note we let the DataContext flow through implicitly, which is (often) a sign of good design.

Upvotes: 1

Related Questions