Search code examples
c#wpfmvvminotifypropertychanged

Get PropertyChanged notification from one ViewModel to another


I'm working on my first WPF project. My UI needs to be more interactive. I've got 2 ViewModels. MainWindowViewModel and WorldViewModel.

MainWindow xaml simplified code:

<Window>
    [...]
    <Window.DataContext>
        <vm:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <!--Worlds combobox-->
        <ComboBox Margin="2 0 0 0" MinWidth="100" IsEnabled="{Binding IsWorldsComboEnabled}"
        ItemsSource="{Binding WorldViewModel.Worlds}" SelectedValue="{Binding WorldViewModel.CurrentWorld}"
        DisplayMemberPath="Name"/>
    </Grid>
</Window>

MainWindowViewModel.cs code:

public class MainWindowViewModel : BaseViewModel
{
    public WorldViewModel WorldViewModel { get; set; }

    public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null;

    /// <summary>
    /// Default constructor
    /// </summary>
    public MainWindowViewModel()
    {
        WorldViewModel = WorldViewModel.Instance;
    }
}

WorldViewModel.cs code:

public class WorldViewModel : BaseViewModel
{
    public ObservableCollection<World> Worlds { get; set; }

    public World CurrentWorld { get; set; }

    public static WorldViewModel Instance { get; set; }

    // Called on startup
    public static void Initialize()
    {
        Instance = new WorldViewModel();
    }

    /// <summary>
    /// Default constructor
    /// </summary>
    public WorldViewModel()
    {

    }
}

ViewModels are a bit bigger, but that's minimum needed code. BaseViewModel is a class which delivers NotifyPropertyChanged Interface with PropertyChanged.Fody NuGet package.

My ComboBox must be disabled when Worlds ObservableCollection is null. It works well when IsWorldsComboEnabled is located in WorldViewModel, but I feel that it's not a way to go. Multiple views will depend on WorldViewModel but they will not need IsWorldsComboEnabled property. So it's place is in MainWindowViewModel.

Is there any way to notify MainWindowViewModel when property in WorldViewModel has changed?


Solution

  • The problem with the following line of code is that the setter of IsWorldsComboEnabled will never be executed even when WorldViewModel.Worlds changed, thus your PropertyChangedEventHandler will not be called.

    public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null
    

    You might change to public bool IsWorldsComboEnabled { get; set; } and evaluate the following expression

    IsWorldsComboEnabled = WorldViewModel.Worlds != null;
    

    whenever you change the property WorldViewModel.Worlds.

    In your case, where the property is a ObservableCollection, you might register to the CollectionChanged Event

    WorldViewModel.Worlds.CollectionChanged += MyCollectionChangedMethod;
    

    and evaluate the expression there

    private void MyCollectionChangedMethod(object sender, NotifyCollectionChangedEventArgs e)
    {
      IsWorldsComboEnabled = WorldViewModel.Worlds != null;
    }