I have a column of checkboxes in a datagrid.
<DataGridTemplateColumn CanUserResize="False" Header="" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource CheckBoxSelectTypeStyle}" IsChecked="{Binding Path=Selected}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I have a command bound to unchecking and checking.
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
</Style.Triggers>
</Style>
My problem is that if the checkboxes start as unchecked and you check one, then no commands are fired (This is the problem). If you then uncheck the same checkbox, the uncheck command will fire (As expected). If you then check the same checkbox again, the check command will fire (As expected). Everything will work fine for that checkbox at that point, but the others still have the same problem.
If a checkbox starts as checked it will work fine. My question is how do I make the command fire when the checkbox starts as unchecked. I can't find any reason for it not to work.
Response to suggestion:
I tried to add a trigger for Null
, but it has the exact same problem, nothing changed.
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
</Style.Triggers>
ViewModel Code
public ICommand CheckedCommand { get; set; }
public ICommand UncheckedCommand { get; set; }
CheckedCommand = new RelayCommand<IList>(Checked);
UncheckedCommand = new RelayCommand<IList>(Unchecked);
private void Checked(IList selectedItems)
{
ChangedChecked(selectedItems, true);
}
private void Unchecked(IList selectedItems)
{
ChangedChecked(selectedItems, false);
}
private void ChangedChecked(IList selectedItems, bool selected)
{
if (selectedItems.HasValue())
foreach (var item in selectedItems)
if(item is SelectedTypeModel) (item as SelectedTypeModel).Selected = selected;
}
RelayCommand implements ICommand. As I mentioned before, the Checked
method is not called when the checkbox starts as unchecked, but it is called when it is checked, unchecked, and checked again or if it starts checked and is unchecked.
What I'm Trying To Do
I have a DataGrid with a column of CheckBoxs. I want to be able to highlight multiple rows, then check/uncheck a CheckBox in one of the selected rows and have all the other rows update to be the same. I also have a keyword filter for the datagrid, so the DataGrid is binding to a ListCollectionView.
Output Information
I enabled debug information for data binding and get this message:
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Selected; DataItem=null; target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')
I'm still not sure how to use this information to correct the problem though.
SOLUTION
I did not fix my original problem and I still don't know why it doesn't work correctly, but I have used another method with the same desired result. Here is the changed code:
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="Command" Value="{Binding DataContext.CheckedChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding Converter="{StaticResource SelectedItemsCheckedMultiValueConverter}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" Path="SelectedItems"/>
<Binding RelativeSource="{RelativeSource Self}" Path="IsChecked"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
public ICommand CheckedChangedCommand { get; set; }
CheckedChangedCommand = new RelayCommand<Tuple<IList, bool>>(CheckedChanged);
eventhandler
code for theCheckbox.CheckChanged
event. – BrianWPF
to be helpful in this issue :( – Brian