I have a custom button control which has a dependency property "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); }
}
And implements an interface
public interface IRequiredControl
{
bool IsEnabled { get; }
bool IsRequired { get; }
}
And I have a converter that uses this interface
<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;
}
I use the converter and bind the image source to the control, as seen below.
<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>
The issue occurs here where the converter is never called when the "IsButtonRequired" viewmodel property is changed. When I set the "IsRequired" of the "AddButton" explicitly to true it works correctly. How can I make the converter update on a change to the "IsRequired" property?
Note I have another solution working where I use a multivalue converter, but I would prefer to get element binding solution working, because it requires much less 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>
The Binding expression
<Image Source="{Binding ElementName=addButton,
Converter={StaticResource IsRequiredToImageConverter}}" />
binds directly to the RequiredButton control, and is not supposed to be triggered when a property of the control changes.
The proper way to implement this is a MultiBinding on both the IsEnabled and IsRequired properties of the control:
<MultiBinding Converter="{StaticResource IsRequiredToImageMultiConverter}">
<MultiBinding.Bindings>
<Binding ElementName="addButton" Path="IsEnabled"/>
<Binding ElementName="addButton" Path="IsRequired"/>
</MultiBinding.Bindings>
</MultiBinding>
The multi-value converter would have to test two boolean values.
Alternatively to using a MultiBinding, a Style with a set of MultiTriggers would also work:
<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>