What I want:
I created a UserControl ImageButton
, where the images can be set in WPF. Usually, I'm reusing the default image for all states but one, but have to configure the control in a very verbose way (see WPF snipped below). What I'd like to achieve is, that every image that is not set, just uses the default image.
What I have:
This is the way I'm describing the ImageButton
at the moment:
<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"/>
This is the style im using:
<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>
And this is the code:
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)
//
}
What I've tried so far:
1. I already tried checking if the image is set like this, which does not work and the code seems to never even reach the getter at all...
get { return (ImageSource)GetValue(HoverImageProperty) ?? DefaultImage; }
2. Also, setting a TargetNullValue
like recommended here does not work ("The member "TargetNullValue" is not recognized or is not accessible."):
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="ButtonImage" Property="Source"
Value="{Binding DownImage, RelativeSource={RelativeSource TemplatedParent}}"
TargetNullValue="{Binding DefaultImage, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
3. The last thing I did was trying to set a PriorityBinding
, like recommended 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>
But that returns the following error:
A 'Binding' cannot be set on the 'Path' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
What I'll have to do:
What would be the right way to fall back to a another DependencyProperty
in case the one I'm looking for is not set?