具有附加属性的样式在根命名空间中有效,在嵌套命名空间中或在被外部程序集访问时失败
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 的附加 属性。
符合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 的附加 属性。