25
votes

I often bind the IsExpanded and IsSelected properties of a TreeViewItem to my viewmodel. This for example makes it possible to make an item pre-expanded when the tree is loaded or expand an item when it gets selected.

The XAML looks like this:

<Window x:Class="StyleSetterDatatypeTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:test="clr-namespace:StyleSetterDatatypeTest"
            Title="MainWindow" Height="350" Width="525"
            mc:Ignorable="d"
            d:DataContext="{d:DesignInstance test:TestViewModel, IsDesignTimeCreatable=True}">

    <TreeView ItemsSource="{Binding Items}">
        <TreeView.Resources>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsExpanded" Value="{Binding ItemExpanded}"/>
                <Setter Property="IsSelected" Value="{Binding ItemSelected}"/>
            </Style>

            <HierarchicalDataTemplate DataType="{x:Type test:TestItemViewModel}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</Window>

And my viewmodel could look like this:

public class TestItemViewModel
{
    public bool ItemExpanded { get; set; }

    public bool ItemSelected { get; set; }

    public string Name { get; set; }

    public string[] Children
    {
        get { return new [] {"Child 1", "Child 2"}; }
    }
}

This works fine in execution and designer, but Resharper does not find the ItemSelected and ItemExpanded properties in the Bindings and underlines them as a warning.
I can understand why it doesn't find them (i never specified "TestViewModel" as the Datacontext type for the Style), but how can i fix this? There is no such thing as a Style-Design-Datacontext...

UPDATE:

The problem here is, the style is defined in the TreeView and there the DataContext is clearly set to a TestViewModel. The checker doesn't get, that what I style is a TreeViewItem and this item has a DataContext of TestItemViewModel (Type of an ItemsSource element).

Oh, and I also tried setting the style in TreeView.ItemContainerStyle instead if TreeView.Resources (here it should be clear the DataContext has to be a TextItemViewModel), but that doesn't change anything...

2
Use relativeSource bindingVimal CK
Isn't that only for finding other views? I edited my viewmodel property names to make it more clear i am binding to the viewmodel.JCH2k

2 Answers

60
votes

@lhildebrandt's answer is generally right, but in my case this solution produces errors that totally disable displaying the view in designer. Specifying <d:Style.DataContext> inside <Style> tag helped me.

<Style>
    <d:Style.DataContext>
        <x:Type Type="local:MyTreeItem" />
    </d:Style.DataContext>
    <!--usual setters, triggers, etc.-->
</Style>

In this way d:DataContext can also be specified for controls, and we can provide it interfaces, nested classes and even generics without any errors: https://stackoverflow.com/a/46637478/5598194

2
votes

Have you tried:

    <Style TargetType="TreeViewItem" d:DataContext="{d:DesignInstance     
 test:TestItemViewModel}">

Atleast for me the properties are highlighted and shown with IntelliSense in VS 2015 and R#9.

Seems to be an identical solution to Specify datacontext type on listbox ItemContainer in style