如果未设置,则从一个依赖项属性回退到另一个依赖项属性

本文关键字:依赖 属性 一个 回退 另一个 设置 如果 | 更新日期: 2023-09-27 18:29:08

我想要的:

我创建了一个用户控件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.我已经尝试检查图像是否像这样设置,这不起作用,代码似乎甚至根本无法到达getter...

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

2. 此外,设置此处推荐的TargetNullValue不起作用("成员"目标空值"无法识别或无法访问。

<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,就像这里推荐的那样:

<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>

但这会返回以下错误:

不能在类型为"绑定"的"路径"属性上设置"绑定"。"绑定"只能在依赖对象的依赖属性上设置。

我必须做什么:

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

如果未设置,则从一个依赖项属性回退到另一个依赖项属性

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

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

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

在以下情况下,绑定将成功返回值:

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

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

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

你应该在你的PriorityBinding中重新排列你的Binding Path......试试这个:

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

有关详细信息,还可以通读 Tech Pro 网站上的 WPF 教程 - 优先级绑定教程。

<小时 />

更新>>>

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