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?
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;
}