具有附加属性的样式在根命名空间中有效,在嵌套命名空间中或在被外部程序集访问时失败

Style with Attached Properties Works In Root NameSpace, Fails in Nested Namespace or when accessed by external assembly

符合Minimal, Complete, and Verifiable Example要求:

以下资源字典:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:MCVE">
    <RadialGradientBrush x:Key="Glow">
        <RadialGradientBrush.RelativeTransform>
            <TranslateTransform X="0.0" Y="0.5" />
        </RadialGradientBrush.RelativeTransform>
        <GradientStop Color="#B28DD8FF" Offset="0.0" />
        <GradientStop Color="#008DD8FF" Offset="1.0" />
    </RadialGradientBrush>
    <Style x:Key="GlassButton" TargetType="{x:Type Button}">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="l:GlassButton.Glow" Value="{StaticResource Glow}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border
                        Background="{Binding
                            Background,
                            RelativeSource={RelativeSource
                                TemplatedParent}}"
                        BorderBrush="{Binding
                            BorderBrush,
                             RelativeSource={RelativeSource 
                                TemplatedParent}}"
                        BorderThickness="{Binding
                            BorderThickness,
                            RelativeSource={RelativeSource 
                                TemplatedParent}}"
                        CornerRadius="10">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Border
                                x:Name="brdGlow"
                                Background="{Binding
                                            (l:GlassButton.Glow),
                                            RelativeSource={RelativeSource
                                                TemplatedParent}}"
                                Opacity="0" BorderThickness="1" Grid.RowSpan="2"
                                VerticalAlignment="Stretch" CornerRadius="4"/>
                            <ContentPresenter Grid.RowSpan="2"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Duration="0:0:0.3" FillBehavior="HoldEnd"
                                        From="0.0"
                                        Storyboard.TargetProperty="(UIElement.Opacity)"
                                        Storyboard.TargetName="brdGlow" To="1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Duration="0:0:0.3" FillBehavior="Stop" From="1"
                                        Storyboard.TargetProperty="(UIElement.Opacity)"
                                        Storyboard.TargetName="brdGlow" To="0.0" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

App.xaml 中的引用:

<Application
    x:Class="MCVE.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MCVE"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MCVEStyle/GlassButton.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

在主要 Window 中:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:l="clr-namespace:MCVE"
    xmlns:lib="clr-namespace:System;assembly=mscorlib"
    x:Class="MCVE.MainWindow"
    mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
    <Button Style="{StaticResource GlassButton}"/>
</Window>

并定义附件属性:

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MCVE {
    public class GlassButton {
        public static readonly DependencyProperty GlowProperty;
        static GlassButton( ) {
            GlowProperty = DependencyProperty.RegisterAttached(
                "Glow", typeof( Brush ), typeof( GlassButton ) );
        }

        public static Brush GetGlow( Button source ) =>
            source.GetValue( GlowProperty ) as Brush;
        public static void SetGlow( Button target, Brush value ) =>
            target.SetValue( GlowProperty, value );
    }
}

此代码有效。如果您 运行 应用程序,您会注意到,当您将光标悬停在 window 上时,光晕会淡入,然后当鼠标不再位于 [=48= 上方时光晕会淡出=].

这很好。

但是,当我嵌套 class 名称 space、 并通过将 l 从 MCVE 更改为 MCVE.NewNameSpace[=41= 来反映 ResourceDictionary 中的更改],和 运行 程序,我在调试 window 中得到这个错误:

System.Windows.Data Error: 40 : BindingExpression path error: '(l:GlassButton.Glow)' property not found on 'object' ''Button' (Name='')'. BindingExpression:Path=(l:GlassButton.Glow); DataItem='Button' (Name=''); target element is 'Border' (Name=''); target property is 'Background' (type 'Brush')

为什么会这样?

编辑:

当我试图通过另一个程序集引用此样式和附加属性时,也会发生这种情况,无论 class 名称space 是否嵌套。

我无法理解 运行 你的代码 - 我总是遇到这个绑定错误:)

请将您的绑定更改为:

Background="{TemplateBinding l:GlassButton.Glow}"

或指定路径属性:

Background="{Binding Path=(l:GlassButton.Glow), RelativeSource={RelativeSource TemplatedParent}}"

Path 的显式规范是必要的,因为 Binding 的解析似乎被额外的括号 {} 弄糊涂了。正如您所看到的,至少其他一些人也遇到了同样的问题 here

完整:

 <Border
       x:Name="brdGlow"
       Background="{TemplateBinding l:GlassButton.Glow}"
       Opacity="0" BorderThickness="1" Grid.RowSpan="2"
       VerticalAlignment="Stretch" CornerRadius="4"/>

使用它,我可以根据需要移动名称空间,并另外指定来自 xaml 的附加 属性。