如果未设置,则从一个DependencyProperty回退到另一个DependencyProperty

时间:2014-11-05 09:06:35

标签: c# wpf user-controls dependency-properties

我想要的是什么:

我创建了一个UserControl ImageButton,可以在WPF中设置图像。通常,我会重新使用除默认图像以外的所有状态,但必须以非常详细的方式配置控件(请参阅下面的WPF剪辑)。我想要实现的是,每个未设置的图像都只使用默认图像。

我有什么:

这就是我现在描述ImageButton的方式:

<cc:ImageButton x:Name="cmdHideCustomWindowingArea" 
                DefaultImage="/Images/UI/ButtonDefault.png"
                HoverImage="/Images/UI/ButtonDefault.png"
                DownImage="/Images/UI/ButtonActive.png"
                UpImage="/Images/UI/ButtonDefault.png"
                DisabledImage="/Images/UI/ButtonDefault.png"/>

这是我使用的风格:

<Style TargetType="{x:Type cc:ImageButton}">
  <Setter Property="Template" >
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type cc:ImageButton}">
        <Grid x:Name="Grid">
          <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Image x:Name="ButtonImage" Source="{Binding DefaultImage, RelativeSource={RelativeSource TemplatedParent}}"/>
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" />
          </StackPanel>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="true">
            <Setter TargetName="ButtonImage" Property="Source" Value="{Binding HoverImage, RelativeSource={RelativeSource TemplatedParent}}" />
          </Trigger>
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="ButtonImage" Property="Source" Value="{Binding DownImage, RelativeSource={RelativeSource TemplatedParent}}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter TargetName="ButtonImage" Property="Source" Value="{Binding DisabledImage, RelativeSource={RelativeSource TemplatedParent}}" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>  

这是代码:

public class ImageButton : Button
{
    static ImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton),
            new FrameworkPropertyMetadata(typeof(ImageButton)));
    }

    public ImageSource DefaultImage
    {
        get { return (ImageSource)GetValue(DefaultImageProperty); }
        set { SetValue(DefaultImageProperty, value); }
    }
    public static readonly DependencyProperty DefaultImageProperty =
        DependencyProperty.Register("DefaultImage",
        typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null));

    public ImageSource HoverImage
    {
        get { return (ImageSource)GetValue(HoverImageProperty); }
        set { SetValue(HoverImageProperty, value); }
    }
    public static readonly DependencyProperty HoverImageProperty =
        DependencyProperty.Register("HoverImage",
        typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null));

    // 
    // ... and so on for every state (Down, Up, Disabled)
    //
}

到目前为止我尝试了什么:

1。我已经尝试检查图像是否设置为这样,这样做不起作用,而且代码似乎根本没有达到吸气剂......

get { return (ImageSource)GetValue(HoverImageProperty) ?? DefaultImage; }

2。此外,设置TargetNullValue之类的推荐here不起作用(“会员”TargetNullValue“无法识别或无法访问。”):< / p>

<Trigger Property="IsPressed" Value="true">
    <Setter TargetName="ButtonImage" Property="Source" 
            Value="{Binding DownImage, RelativeSource={RelativeSource TemplatedParent}}" 
            TargetNullValue="{Binding DefaultImage, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>

3。我做的最后一件事是尝试设置PriorityBinding,就像推荐here一样:

<Trigger Property="IsMouseOver" Value="true">
    <Setter TargetName="ButtonImage" Property="Source">
        <Setter.Value>
            <PriorityBinding>
                <Binding Path="{Binding HoverImage, RelativeSource={RelativeSource TemplatedParent}}"/>
                <Binding Path="{Binding DefaultImage, RelativeSource={RelativeSource TemplatedParent}}"/>
            </PriorityBinding>
        </Setter.Value>
    </Setter> 
</Trigger>

但是会返回以下错误:

  

无法在“绑定”类型的“路径”属性上设置“绑定”。 '绑定'只能在DependencyObject的DependencyProperty上设置。

我需要做什么:

如果我正在寻找的那个没有设置,那么回到另一个DependencyProperty的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

听起来好像在寻找PriorityBinding Class(尽管您之前尝试过使用它)。在链接的页面中,PriorityBinding

  

描述附加到单个绑定目标属性的Binding对象的集合,该属性从集合中的第一个绑定接收其值,该绑定成功生成值。

     

...

     

PriorityBinding允许您将绑定目标(目标)属性与绑定列表相关联。成功返回值的第一个绑定将成为活动绑定。

     

如果出现以下情况,绑定会成功返回值:

     

1.绑定源的路径成功解析。

     

2.值转换器(如果有)能够转换结果值。

     

3.结果值对目标属性有效。

您应该重新安排Binding Path中的PriorityBinding ...尝试此操作:

<PriorityBinding>
    <Binding Path="HoverImage" RelativeSource="{RelativeSource TemplatedParent}}" />
    <Binding Path="DefaultImage" RelativeSource="{RelativeSource TemplatedParent}}" />
</PriorityBinding>

有关详细信息,您还可以阅读Tech Pro网站上的WPF Tutorial - Priority Bindings教程。


更新&gt;&gt;&gt;

正如您正确指出的那样,PriorityBinding确实会接受null作为有效的返回值。但是,您可以使用自定义IValueConverter实现来解决该问题,该实现在实际值为DependencyProperty.UnsetValue时返回null