Question

How do I bind grid to selected tree view item in WPF? In short when user of my app clicks on tree view item, then I want to run command that would load some data and present it on grid. Based on item's underlying type I want to bind to different commands.

XAML

<TreeView ItemsSource="{Binding Path=SomeCollection, UpdateSourceTrigger=PropertyChanged}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=., Converter={StaticResource GetElementTypeConverter}}" Value="{x:Type Models:SomeType}">
                    // WHAT CODE GOES HERE?
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=., Converter={StaticResource GetElementTypeConverter}}" Value="{x:Type Models:SomeOtherType}">
                    // WHAT CODE GOES HERE?
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

I'd like to handle click event in MVVM manner.

Was it helpful?

Solution

In WPF, we deal with different data types by defining different DataTemplates. In your case, you could already have defined some. If not, do so now, and in these DataTemplates, you can set the relevant ICommands. You can do this in several ways, but one easy way is just to define your content inside a 'blank' Button:

<DataTemplate DataType="{x:Type YourDataTypePrefix:YourDataType}">
    <Button Command="{Binding SomeCommand}">
        <Button.Template>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <!-- Define your YourDataType item content here -->
                </Grid>
            </ControlTemplate>
        </Button.Template>
    </Button>
</DataTemplate>
<DataTemplate DataType="{x:Type YourDataTypePrefix:OtherDataType}">
    <Button Command="{Binding SomeOtherCommand}">
        <Button.Template>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <!-- Define your OtherDataType item content here -->
                </Grid>
            </ControlTemplate>
        </Button.Template>
    </Button>
</DataTemplate>

UPDATE >>>

That seems strange that you say you can't select the TreeViewItem with that Button. However, you could try using a ToggleButton to bind to the TreeViewItem.IsSelected property instead:

<ToggleButton Command="{Binding SomeCommand}" IsChecked="{Binding IsSelected, 
    RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}">
    <ToggleButton.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Grid>
                <!-- Define your YourDataType item content here -->
            </Grid>
        </ControlTemplate>
    </ToggleButton.Template>
</ToggleButton>

If that still doesn't work, then use an AttachedProperty to handle the PreviewMouseDown event on a Grid in the DataTemplates. You can find lots of online documentation about handling events with AttachedPropertys, so I won't go over that again here. However, if you did that (and that is the better solution), then you could then do something like this:

<DataTemplate DataType="{x:Type YourDataTypePrefix:YourDataType}">
    <Grid Attached:MouseEvents.PreviewMouseDown="{Binding SomeCommand}">
        <!-- Define your YourDataType item content here -->
    </Grid>
</DataTemplate>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top