Binding a resource to a custom control property

眉间皱痕 提交于 2019-12-31 03:18:52

问题


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.


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/4924621/binding-a-resource-to-a-custom-control-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!