How can i specify a designer datacontext for a style, so Resharper finds my properties?
Asked Answered
B

3

34

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

Binominal answered 19/1, 2015 at 14:58 Comment(2)
Use relativeSource bindingDieterich
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.Binominal
A
74

@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://mcmap.net/q/451082/-d-designinstance-with-an-interface-type

Adriatic answered 9/10, 2017 at 1:23 Comment(7)
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 @Binominal mark this answer as the solution.Pani
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 !Potheen
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"Socialize
How come that it doesn't work when using <Style d:DataContext=local:MyTreeItem..., but works when doing <d:Style.DataContext>...?Inquisitionist
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 "schemas.microsoft.com/expression/blend/2008". and the designer only displays an 'Invalid Markup' message.Artificiality
This is fixed in 16.7.3 of VS 2019Portis
I was able to get this to work as an attribute on the Style tag like <Style d:Style.DataContext="{d:DesignInstance Type={x:Type local:MyType}}" .... This allowed for ReSharper to recognize the Binding paths correctly and didn't cause any designer errors.Uncial
A
5

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

Azalea answered 5/10, 2016 at 19:55 Comment(5)
This doesn't work for me. I get the error Property 'DataContext' is not attachable to elements of type 'Style'Aerugo
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.Fabozzi
@kux dou you have a solution how to hide this "error" ?Blaeberry
@DominicJonas not for d:DataContext. now I use <d:Style.DataContext> see answer from N. Kudryavtsev https://mcmap.net/q/434973/-how-can-i-specify-a-designer-datacontext-for-a-style-so-resharper-finds-my-propertiesFabozzi
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.Cityscape
U
0

I was able to get this to work without any designer errors, and ReSharper recognized the binding paths as valid:

        <Style TargetType="TreeViewItem" d:Style.DataContext="{d:DesignInstance Type={x:Type local:TestItemViewModel}}">
            <Setter Property="IsExpanded" Value="{Binding ItemExpanded}"/>
            <Setter Property="IsSelected" Value="{Binding ItemSelected}"/>
        </Style>

I'm using VS 17.8.6 and ReSharper 2023.3.3.

Uncial answered 26/3 at 16:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.