【问题标题】:Binding a resource to a custom control property将资源绑定到自定义控件属性
【发布时间】:2011-06-22 21:59:35
【问题描述】:

我正在创建一个自定义按钮,该按钮通常显示略微褪色的文本,并在 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')

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

【问题讨论】:

    标签: wpf wpf-controls binding


    【解决方案1】:

    RelativeSource TemplatedParent only (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 相同的前景色的任何控件上使用绑定。

    【讨论】:

    • 将接受的答案更改为这个答案——关于 FindAncestor 的提示原来是解决方案中的一个关键因素。
    • 嗯,我认为相对源绑定沿着可视化树向上走,资源是逻辑树的成员。我总是把这件事搞砸。如果有人碰巧知道 100% 并阅读此内容,请发表评论,谢谢。
    【解决方案2】:

    问题是您不能在资源中定义的元素上使用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

    【讨论】:

    • 被接受为第一个回答者和 +1
    猜你喜欢
    • 2011-05-11
    • 2011-08-29
    • 2013-12-25
    • 1970-01-01
    • 2012-08-29
    • 2018-03-11
    • 1970-01-01
    • 2018-04-09
    相关资源
    最近更新 更多