1

I have a TreeView setup with a HierarchialDataTemplate. It's ItemsSource is bound to a collection of Overlay objects in my viewmodel, where each Overlay has a collection of Layer objects (thus the HierarchialDataTemplate). For each Overlay, I'm displaying a CheckBox and a Label which is simply bound to the Overlay's Name property.

Each time one of the checkboxes is checked/unchecked, the current Overlay and the IsChecked property of the CheckBox will be sent as command parameters to my viewmodel. I'm using a MultiValueConverter to send these.

My issue is that the IsChecked property of the CheckBox never changes. I've tried using both DataTriggers and setting the Command property directly, but I get the same result.

Below is the related .xaml for the TreeView. This is using the Command property.

<TreeView ItemsSource="{Binding OverlaysViewSource}" Name="LayersTreeView">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Layers}" >
            <StackPanel>
                <CheckBox IsChecked="True" Command="{Binding DataContext.SetLayersCmd, RelativeSource={RelativeSource AncestorType=UserControl}}">
                    <CheckBox.CommandParameter>
                        <MultiBinding Converter="{StaticResource multiValueConverter}">
                            <Binding RelativeSource="{RelativeSource Self}" />
                            <Binding />
                        </MultiBinding>
                    </CheckBox.CommandParameter>
                </CheckBox>
                <Label Content="{Binding Name}" />
            </StackPanel>
            <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <Label Content="{Binding Name}" />
                            </StackPanel>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Here's the version using DataTriggers:

<TreeView ItemsSource="{Binding OverlaysViewSource}" Name="LayersTreeView">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Layers}" >
            <StackPanel>
                <CheckBox>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Checked">
                            <i:InvokeCommandAction Command="{Binding DataContext.SetLayersCmd, RelativeSource={RelativeSource AncestorType=UserControl}}" >
                                <i:InvokeCommandAction.CommandParameter>
                                    <MultiBinding Converter="{StaticResource multiValueConverter}">
                                        <Binding RelativeSource="{RelativeSource AncestorType=CheckBox}" />
                                        <Binding/>
                                    </MultiBinding>
                                </i:InvokeCommandAction.CommandParameter>
                            </i:InvokeCommandAction>
                        </i:EventTrigger>
                        <i:EventTrigger EventName="Unchecked">
                            <i:InvokeCommandAction Command="{Binding DataContext.SetLayersCmd, RelativeSource={RelativeSource AncestorType=UserControl}}" >
                                <i:InvokeCommandAction.CommandParameter>
                                    <MultiBinding Converter="{StaticResource multiValueConverter}">
                                        <Binding RelativeSource="{RelativeSource AncestorType=CheckBox}"/>
                                        <Binding />
                                    </MultiBinding>
                                </i:InvokeCommandAction.CommandParameter>
                            </i:InvokeCommandAction>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </CheckBox>
                <Label Content="{Binding Name}" />
            </StackPanel>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Name}" />
                    </StackPanel>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Here's my MultiValueConverter:

public class MultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        CheckBox cb = (CheckBox)values[0];
        Overlay overlay = (Overlay)values[1];
        return new object[] { cb.IsChecked, overlay };
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

I'm checking the IsChecked value in both the converter and the command in my view model. It never changes. The GUI never reflects a change in the CheckBox either.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
pfinferno
  • 1,779
  • 3
  • 34
  • 62
  • 3
    What if you put a boolean property in the Layers object and bind IsChecked to that? Then you can simple pass the layer in the command and not worry about the multibinding. (Don't worry about the vote to close, there is some serial vote-to-close person patrolling the wpf tag.) – geometrikal Oct 18 '19 at 04:04
  • So the `Overlay` and `Layer` objects are third party objects that are used extensively in the app. I'd rather not create a new class for this but looks like I might have to go that route. I just don't understand why the checkbox wouldn't change. – pfinferno Oct 18 '19 at 12:42
  • I wonder if maybe the first binding should be to the IsChecked property rather than the control itself. – geometrikal Oct 18 '19 at 13:05

0 Answers0