依赖项 属性 更改时元素绑定未更新

Element binding not updating when dependency property changed

我有一个自定义按钮控件,它具有依赖项 属性“IsRequired”

    public static readonly DependencyProperty IsRequiredProperty = DependencyProperty.RegisterAttached(nameof(IsRequired), typeof(bool), typeof(RequiredButton), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));

    public bool IsRequired
    {
        get { return (bool)GetValue(IsRequiredProperty); }
        set { SetValue(IsRequiredProperty, value); }
    }

并实现一个接口

public interface IRequiredControl
{
    bool IsEnabled { get; }
    bool IsRequired { get; }
}

我有一个使用这个接口的转换器

   <sharedConverters:IsRequiredToImageConverter x:Key="IsRequiredToImageConverter"
                                                 DisabledImage="{StaticResource DisabledDrawing}"
                                                 NormalImage="{StaticResource NormalDrawing}"
                                                 RequiredImage="{StaticResource IsRequiredDrawing}" />


    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is IRequiredControl requiredControl)
        {
            return !requiredControl.IsEnabled ? DisabledImage : requiredControl.IsRequired ? RequiredImage : NormalImage;
        }

        return DependencyProperty.UnsetValue;
    }

我使用转换器并将图像源绑定到控件,如下所示。

<DataTemplate x:Key="RightSideAddTemplate">
    <sharedControls:RequiredButton x:Name="addButton"
                                   Command="{x:Static commands:AddCommand}"
                                   IsRequired="{Binding IsButtonRequired}">
            <Image Source="{Binding ElementName=addButton, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IsRequiredToImageConverter}}" />
    </sharedControls:RequiredButton>
</DataTemplate>

这里出现的问题是,当“IsButtonRequired”视图模型 属性 更改时,转换器永远不会被调用。当我将“AddButton”的“IsRequired”明确设置为 true 时,它​​可以正常工作。如何让转换器根据“IsRequired”的更改进行更新 属性?

注意 我有另一个解决方案在我使用多值转换器的地方工作,但我更愿意让元素绑定解决方案工作,因为它需要更少 xaml。

<Image Style="{StaticResource AddImageButtonStyle}">
     <Image.Source>
           <MultiBinding Converter="{StaticResource IsRequiredToImageMultiConverter}">
               <MultiBinding.Bindings>
                     <Binding ElementName="addButton" Path="IsEnabled" />
                     <Binding Path="IsButtonRequired" />
               </MultiBinding.Bindings>
            </MultiBinding>
         </Image.Source>
     </Image>

绑定表达式

<Image Source="{Binding ElementName=addButton,
                Converter={StaticResource IsRequiredToImageConverter}}" />

直接绑定到 RequiredButton 控件,并且不应在控件的 属性 更改时触发。

实现它的正确方法是在控件的 IsEnabled 和 IsRequired 属性上使用 MultiBinding:

<MultiBinding Converter="{StaticResource IsRequiredToImageMultiConverter}">
    <MultiBinding.Bindings>
        <Binding ElementName="addButton" Path="IsEnabled"/>
        <Binding ElementName="addButton" Path="IsRequired"/>
    </MultiBinding.Bindings>
</MultiBinding>

multi-value 转换器必须测试两个布尔值。


除了使用 MultiBinding,带有一组 MultiTriggers 的 Style 也可以:

<Style TargetType="sharedControls:RequiredButton">
    <Setter Property="Content">
        <Setter.Value>
            <Image Source="{StaticResource DisabledDrawing}"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsEnabled" Value="true" />
                <Condition Property="IsRequired" Value="false" />
            </MultiTrigger.Conditions>
            <Setter Property="Content">
                <Setter.Value>
                    <Image Source="{StaticResource NormalDrawing}"/>
                </Setter.Value>
            </Setter>
        </MultiTrigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsEnabled" Value="true" />
                <Condition Property="IsRequired" Value="true" />
            </MultiTrigger.Conditions>
            <Setter Property="Content">
                <Setter.Value>
                    <Image Source="{StaticResource IsRequiredDrawing}"/>
                </Setter.Value>
            </Setter>
        </MultiTrigger>
    </Style.Triggers>
</Style>