将资源绑定到自定义控件属性

发布于 2024-10-16 13:38:37 字数 1526 浏览 2 评论 0原文

我正在创建一个自定义按钮,该按钮通常显示稍微褪色的文本,并在 MouseOverMouseDown 上显示全强度文本。我在控件的 Generic.xaml 中定义了两个资源来表示这些文本颜色的画笔:

<!-- Text Brushes -->
<SolidColorBrush x:Key="NormalTextBrush" Color="Black" />
<SolidColorBrush x:Key="FadedTextBrush" Color="Gray" />

控件在该配置中编译并正常工作。

但我想让控件用户使用自定义控件的 Foreground 属性来设置文本颜色。因此,我将资源声明更改为:

<!-- Text Brushes -->
<SolidColorBrush x:Key="NormalTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
<SolidColorBrush x:Key="FadedTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorConverter}, ConverterParameter='1.2'}" />

第二个声明使用 HSL 值转换器来淡化文本颜色。

现在该控件不起作用,并且我在输出窗口中收到以下错误:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Foreground; DataItem='TaskButton' (Name='Button1'); target element is 'SolidColorBrush' (HashCode=38118303); target property is 'Color' (type 'Color')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Foreground; DataItem=null; target element is 'SolidColorBrush' (HashCode=47449297); target property is 'Color' (type 'Color')

我不确定数据错误告诉我什么。谁能告诉我发生了什么事以及如何解决它?感谢您的帮助。

I am creating a custom button that shows slightly faded text normally, and full-strength text on a MouseOver or MouseDown. I have defined two resources in the Generic.xaml of my control to represent the brushes for these text colors:

<!-- Text Brushes -->
<SolidColorBrush x:Key="NormalTextBrush" Color="Black" />
<SolidColorBrush x:Key="FadedTextBrush" Color="Gray" />

The control compiles and works fine in that configuration.

But I want to let the control user set the text color, using the custom control's Foreground property. So, I changed the resource declarations to this:

<!-- Text Brushes -->
<SolidColorBrush x:Key="NormalTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
<SolidColorBrush x:Key="FadedTextBrush" Color="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorConverter}, ConverterParameter='1.2'}" />

The second declaration uses an HSL value converter to fade the text color.

Now the control doesn't work, and I get the following error in the output window:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Foreground; DataItem='TaskButton' (Name='Button1'); target element is 'SolidColorBrush' (HashCode=38118303); target property is 'Color' (type 'Color')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Foreground; DataItem=null; target element is 'SolidColorBrush' (HashCode=47449297); target property is 'Color' (type 'Color')

I'm not sure what the Data Error is telling me. Can anyone tell me what's going on and how to fix it? Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘过的浮云 2024-10-23 13:38:37

RelativeSource TemplatedParent (IIRC) 在控件模板中有意义,它指的是应用该模板的控件实例的属性。

UserControl 的内容不是 UserControl 的模板。因此,此绑定不会将父 UserControl 视为可行的目标。

该错误消息是指 SolidColorBrush 没有模板;它不扩展 System.Windows.Controls.Control,这是(大多数)所有模板化 UI 控件的基本类型。请参阅 Control.Template 有关模板的更多信息。

您想要做的是设置 FindAncestor 的相对源。

{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}

这将沿着视觉(或者逻辑?)树查找 UserControl 类型的第一个祖先,然后绑定到名为 Foreground 的公共属性。

但是如果SolidColorBrush被定义为Resource,这将不起作用。资源不是视觉(或逻辑树,或两者?仍然不清楚)的一部分,因此 RelativeSource 绑定将无法遍历树的祖先。

您必须直接在任何您希望与 UserControl 具有相同前景色的控件上使用绑定。

RelativeSource TemplatedParent only (IIRC) has meaning within a control template, and it refers to a property on the instance of the control on which the template is applied.

A UserControl's content is not the template of the UserControl. So this binding won't consider the parent UserControl as a viable target.

The error message refers to the fact that a SolidColorBrush does not have a template; it does not extend System.Windows.Controls.Control, which is the base type of (most) all templated UI controls. See Control.Template for more information about templating.

What you want to do is set a relative source of FindAncestor.

{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}

This will walk up the visual (or is it logical?) tree to find the first ancestor of type UserControl, then bind against a public property called Foreground.

However this will NOT work if the SolidColorBrush is defined as a Resource. Resources are not part of the visual (or logical tree, or both? still not clear) and therefore a RelativeSource binding will not be able to walk the tree's ancestry.

You will have to use the binding directly on whatever control you wish to have the same foreground color as the UserControl.

山色无中 2024-10-23 13:38:37

问题是您不能对资源中定义的元素使用 RelativeSource 绑定,因为它们不是可视树或逻辑树的一部分。

要解决此问题,您只需在设置资源引用的位置(在按钮的控件模板中)设置这些绑定。类似这样:

<ControlTemplate TargetType="{x:Type Button}">
   <Border x:Name="brd" 
           TextBlock.Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}">
      ...
   </Border>
   <ControlTemplate.Triggers>
      <Trigger Property="IsMouseOver"
               Value="True">
          <Setter TargetName="brd"
                  Property="TextBlock.Foreground"
                  Value="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorConverter}, ConverterParameter='1.2'}"/>
      </Trigger>
   </ControlTemplate.Triggers>
</ControlTemplate>

换句话说,您不需要定义资源 - NormalTextBrushFadedTextBrush

The problem is that you cannot use RelativeSource bindings on elements defined in resources, because they are not a part of visual or logical tree.

To fix this you just need to set these binding in places where you set the references to your resources (in the control template of your button). Something like this:

<ControlTemplate TargetType="{x:Type Button}">
   <Border x:Name="brd" 
           TextBlock.Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}">
      ...
   </Border>
   <ControlTemplate.Triggers>
      <Trigger Property="IsMouseOver"
               Value="True">
          <Setter TargetName="brd"
                  Property="TextBlock.Foreground"
                  Value="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorConverter}, ConverterParameter='1.2'}"/>
      </Trigger>
   </ControlTemplate.Triggers>
</ControlTemplate>

In other words, you don't need to define resourses - NormalTextBrush and FadedTextBrush.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文