Search code examples
wpfdependency-propertiesattached-propertieswpf-style

Unable to set my attached property unless it is in a style setter


I have an assembly with a custom Control class the defines an attached property.

public class LayerView : MultiSelector
{   
    public static readonly DependencyProperty PathStyleProperty =
        DependencyProperty.RegisterAttached(
            nameof(PathStyle),
            typeof(Style),
            typeof(LayerView),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));


    public Style PathStyle
    {
        get => (Style)GetValue(PathStyleProperty);
        set => SetValue(PathStyleProperty, value);
    }

    //...etc. etc -- this is a 2,000 lines of code)

}

Later on, in another assembly I try to set this attached property on another custom control in a DataTemplate.

<Style x:Key="OverlayLayerControlStyle" TargetType="{x:Type ItemsControl}">
    <Style.Resources>
        <DataTemplate DataType="{x:Type ana:LineProperty}">
            <!-- ERROR -- cannot Set attached property this way -->
            <ctrl:LineControl                    
                P1="{Binding ValueT.P1}" P2="{Binding ValueT.P2}"
                TextElement.FontSize="20"
                ctrl:LayerView.PathStyle="{StaticResource OutputPathStyle}"/> 

        </DataTemplate>
    </Style.Resources>

</Style>

It does not even build. It gives me build error MC3015

7>C:\Users\jmole\source\repos\Main\Mobile.Common\Resources\CommonLayerViewStyles.xaml(430,21): error MC3015: The attached property 'LayerView.PathStyle' is not defined on 'LineControl' or one of its base classes.

And that's true. It is not supposed to be in LineControl. It is an attached property.

So why am I, above, able to set another attached property like TextElement.FontSize but not my own property?

I found this answer which made me think I might just need to set the property in the body of the element to make it work. I tried that but I got the exact same error

In desperation I tried setting same attached property in regular setter in the style. So I'm setting it on the ItemsControl, not the items within it.

    <!-- This works just fine -->
    
    <Setter Property="ctrl:LayerView.PathStyle" Value="{StaticResource OutputPathStyle}"/>

This builds and runs and functions correctly. Since the PathStyle property inherits, child items do receive it. But I need to be able to set this property in individual items, not the whole layer.

So what did I get wrong wrong with my PathStyle property that I cannot set it like TextElement.FontSize?


Solution

  • I believe that the issue is that your accessors for the attached property are not static.

    Try this:

    public static readonly DependencyProperty PathStyleProperty =
        DependencyProperty.RegisterAttached(
            nameof(PathStyle),
            typeof(Style),
            typeof(LayerView),
            new FrameworkPropertyMetadata(null, 
                FrameworkPropertyMetadataOptions.AffectsRender));
    
    
    // Declare static get/set accessor methods
    public static Style GetPathStyle(UIElement target) =>
        (Style)target.GetValue(PathStyleProperty);
    public static void SetPathStyle(UIElement target, Style value) =>
        target.SetValue(PathStyleProperty, value);