31

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...

JCH2k
  • 3,361
  • 32
  • 25

2 Answers2

69

@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

N. Kudryavtsev
  • 3,556
  • 1
  • 26
  • 30
  • 1
    Fantastic! Assigning the d:DataContext as an attached property (as I normally do for Window/UserControl) caused a designer-error, but ReSharper was able to find and verify the properties. Assigning it inside the style as your answer does, removes the designer-error, and still lets ReSharper do its thing! I Suggest @JCH2k mark this answer as the solution. – Bendik August Nesbø Mar 02 '18 at 11:24
  • Finally got rid of those warnings. Thanks ! Being able to specify interfaces (as well as nested classes and generics) is a really nice plus, I have a few abstract classes I can remove now ! – misterfrb Mar 21 '18 at 13:52
  • 3
    Anyone having troubles with this: This is how the namespaces should be `xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"` `xmlns:d="http://schemas.microsoft.com/expression/blend/2008"` `mc:Ignorable="d"` – CSharpie Jul 12 '18 at 09:09
  • 5
    How come that it doesn't work when using ` – asaf92 Aug 05 '19 at 13:47
  • 3
    It worked for a while, but now (VS 16.7.2), I get the following error: The name "Style" does not exist in the namespace "http://schemas.microsoft.com/expression/blend/2008". and the designer only displays an 'Invalid Markup' message. – Yet Another Code Maker Aug 28 '20 at 13:31
  • This is fixed in 16.7.3 of VS 2019 – Jason Stevenson Sep 15 '20 at 13:05
  • 1
    This doesn't work for me in VS 16.11.9. Even with the DataContext broken out as a tag, VS still complains that `Property 'DataContext' is not attachable to elements of type 'Style'.` – hypehuman Jul 08 '22 at 19:11
3

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

Community
  • 1
  • 1
lhildebrandt
  • 294
  • 1
  • 9
  • 1
    This doesn't work for me. I get the error `Property 'DataContext' is not attachable to elements of type 'Style'` – Dan Stevens Feb 14 '18 at 12:15
  • 2
    this would work for ReSharper BUT designer shows an error (since VS 2015) `The property "DataContext" does not exist in the "http://schemas.microsoft.com/expression/blend/2008" namespace.` – Kux Mar 24 '18 at 18:24
  • @kux dou you have a solution how to hide this "error" ? – Dominic Jonas Mar 26 '18 at 07:27
  • 1
    @DominicJonas not for `d:DataContext`. now I use `` see answer from N. Kudryavtsev https://stackoverflow.com/a/46637672/2369575 – Kux Mar 30 '18 at 12:06
  • BEWARE: if you try using this construct, it will initially seem to work, but XAML Hot Reload will start silently failing from that moment on. Do not use this construct, use the one suggested by N. Kudryavtsev. – Mike Nakis Jun 12 '23 at 11:45