I have a button that has four dependency properties, each representing a state the button is in. Each state's source is an image. What I would like to achieve is an ability for any state other than NormalState
to bind to NormalState's
value if it's own value was not provided.
I tried doing it using DataTrigger
, but I'm getting an exception:
Set property 'System.Windows.Setter.Value' threw an exception.
It's position points to this line:
<Setter Property="MouseOverState" Value="{TemplateBinding NormalState}"/>
Here's part of the XAML code, which is located in a ResourceDictionary
:
<Style TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Grid>
<ContentControl>
<Grid>
<Image x:Name="Normal" Source="{TemplateBinding NormalState}" Visibility="Visible"/>
<Image x:Name="MouseOver" Source="{TemplateBinding MouseOverState}" Visibility="Hidden"/>
<Image x:Name="Pressed" Source="{TemplateBinding PressedState}" Visibility="Hidden"/>
<Image x:Name="Disabled" Source="{TemplateBinding DisabledState}" Visibility="Hidden"/>
</Grid>
</ContentControl>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=MouseOverState}" Value="{x:Null}">
<Setter Property="MouseOverState" Value="{TemplateBinding NormalState}"/>
<Setter Property="Width" Value="50"/>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Normal" Property="Visibility" Value="Hidden"/>
<Setter TargetName="MouseOver" Property="Visibility" Value="Visible"/>
<Setter TargetName="Pressed" Property="Visibility" Value="Hidden"/>
<Setter TargetName="Disabled" Property="Visibility" Value="Hidden"/>
</Trigger>
...and so on...
Here's the use code:
In the template code you may notice the Setter
of Width
to the value of 50
. This was done to check if that code detects missing ouseOverState
property at all; and it does. However, when I try to set the MouseOverState property, I get the Setter Exception described above. Does anyone know what I'm doing wrong or is there an easier way? I couldn't figure out a way to do it with the control's code-behind within the dependency property code (that dependency code is pretty common to all other, so I'm not going to post it here, unless it's requested).
Here's another way I tried, but it did not work either (throwing the same exception, which does not provide a whole lot of details):
<Setter TargetName="Normal" Property="Source" Value="{TemplateBinding NormalState}"/>
I couldn't find a way, after much searching, of accomplishing this task within the C# code using Dependency Property setters either. However, if someone knows of it, that'll be a very acceptable solution as well.
TemplateBinding can only be used within a ControlTemplate.TemplateBinding is used for binding to the element properties within the template definition.Setters do not support TemplateBinding.
A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent}}.
Visit this link1 and link2 for binding
in your case try with
<Setter TargetName="Normal" Property="Source" Value="{Binding Path=Propertyname, RelativeSource={RelativeSource AncestorType={x:Type local:ImageButton}}"/>
or
<Setter TargetName="Normal" Property="Source" Value="{Binding Path=Propertyname, RelativeSource={RelativeSource TemplatedParent}}"/>