依赖项 属性 更改时元素绑定未更新
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>
我有一个自定义按钮控件,它具有依赖项 属性“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>