如何在资源中使用绑定来避免错误?
我现在正在研究我的第一个 wpf 项目。我在以下控件Style
中Windows.Resource
加入了参考。
<Window.Resources>
<Style x:Key="EmojiButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="1" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="4"
Opacity="1.0"
ShadowDepth="0"
Color="Gray" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border
x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ContentPresenter
x:Name="contentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Focusable="False"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefaulted" Value="true" />
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="TextBlock.Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="5"
ShadowDepth="0"
Color="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Foreground, Mode=OneWay, Converter={StaticResource SingleValueDebugPrintConverter}}" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="OrangeRed" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="TextBlock.Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="2"
ShadowDepth="0"
Color="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Foreground, Mode=OneWay, Converter={StaticResource SingleValueDebugPrintConverter}}" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="DarkRed" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="contentPresenter" Property="TextElement.Foreground" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
它运行良好,但是在应用程序启动时出现错误。
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Foreground; DataItem=null; target element is 'DropShadowEffect' (HashCode=65300541); target property is 'Color' (type 'Color')
我确定错误是由于Color="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Foreground, Mode=OneWay, Converter={StaticResource SingleValueDebugPrintConverter}}"
,在被其他控件引用之前,绑定Windows.Resource
没有祖先。
我这样做是否正确?错误是可以避免的吗?
更新#1
几个小时以来一直在研究类似的问题,但没有一个与我遇到的问题相符。
绑定目标需要是可视化树的一部分。资源字典中没有数据上下文。确切的修复将取决于您的场景细节。有关一般性建议,请参阅副本。——彼得·杜尼霍
Peter Duniho 的回答可能解释了为什么binding
inWindow.Resource
不起作用,但我找不到任何解决方法。ProxyElement
其他帖子中提到的技巧是绑定到DataContext
not Ancestor
。
更新#2
无论如何,我找到了正确的方法。使用TemplateBinding
而不是FindAncestor
.
<Window.Resources>
<Style x:Key="EmojiButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="1" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="4"
Opacity="1.0"
ShadowDepth="0"
Color="Gray" />
</Setter.Value>
</Setter>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border
x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ContentPresenter
x:Name="contentPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Focusable="False"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="TextBlock.Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="8"
ShadowDepth="0"
Color="{TemplateBinding Property=Foreground}" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="TextBlock.Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="3"
ShadowDepth="0"
Color="{TemplateBinding Property=Foreground}" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="contentPresenter" Property="TextElement.Foreground" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
感谢样式和模板 (WPF .NET)。Stackoverflow 确实需要先审查某人的问题,然后再将其作为duplicate
.