I have an MVVM WPF project with the following code:
MultiplexerVM.cs
public class MultiplexerVM : BaseViewModel
{
public ObservableCollection<MultiplexVM> Multiplexes { get; set; } = new();
public MultiplexVM SelectedMultiplex { get; set; }
public ICommand CheckAll => new CheckBoxCommand(Multiplexes);
}
MultiplexVM.cs
public class MultiplexVM : BaseViewModel
{
public bool IsChecked { get; set; }
}
MultiplexerV.xaml
<UserControl x:Class="MKVStudio.Views.MultiplexerV"
xmlns:vm="clr-namespace:MKVStudio.ViewModels"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<UserControl.Resources>
<s:Boolean x:Key="True">True</s:Boolean>
<s:Boolean x:Key="False">False</s:Boolean>
</UserControl.Resources>
<Grid>
<ListView ItemsSource="{Binding Multiplexes}"
SelectedItem="{Binding SelectedMultiplex}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}"Margin="3"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...
</GridView>
</ListView.View>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding CheckAll}"
CommandParameter="{StaticResource True}">
<MenuItem.Header>
<TextBlock Text="Check all"/>
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding CheckAll}"
CommandParameter="{StaticResource False}">
<MenuItem.Header>
<TextBlock Text="Uncheck all"/>
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</Grid>
</UserControl>
My goal is to bind IsEnabled of the context menu items to the property IsChecked of MultiplexVM.cs. The idea was to implement an IValueConverter (passing Multiplexes as value and bool as parameter). The converter returns value.Where(m => m.IsChecked == parameter).Count > 0. Essentially, when all Multiplexes are unchecked the menu item Check all is enabled and the menu item Uncheck all is disabled. The reverse thing is happening when all Multiplexes are checked. The problem here is that the converter is invoked only once when it is declared basically, and checking and unchecking the items does not trigger the converter to see what is happening.
I have tried to implement an IMultiValueConverter (but failing to use it correctly) and pass three values like this:
<MenuItem.IsEnabled>
<MultiBinding>
<Binding Source="{Binding Multiplexes.Count}" />
<Binding Source="{Binding Multiplexes}" />
<Binding Source="{StaticResource True}" /> <!--respectivly False to the other menu item-->
</MultiBinding>
</MenuItem.IsEnabled>
This doesn't work. I've tried <Binding Path="Multiplexes.Count" /> and <Binding Path="Multiplexes" />, but also doesn't work (the values passed to the converter are Unset).
Is my idea for using MultiBinding even feasible and what am I doing wrong when using it?
Why do you need to bind IsChecked to IsChecked and IsEnabled at once? This is very strange if you look at it from the Single Responsibility Principle. If you are sure that you are doing it right, you can do it like this:
And make your class look like something like this: