I'm building Windows Phone app and I created a custom icon button that will be used over and over again. The button looks pretty much like the following picture:

To try to follow the DRY (Don't Repeat Yourself) principle I created a class that basically inherited from Button and added a custom parameter of type ControlTemplate called IconTemplate
I omitted the part about the property for the Text for brevity
public class IconButton : Button
{
public static readonly DependencyProperty IconTemplateProperty =
DependencyProperty.Register(
"IconTemplate",
typeof(ControlTemplate),
typeof(IconButton),
null);
public ControlTemplate IconTemplate
{
get { return (ControlTemplate)GetValue(IconTemplateProperty); }
set { SetValue(IconTemplateProperty, value); }
}
}
After creating the class I made a Resource called Generic.xaml that applied some style to this class.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:PiadasEngracadas.Controls"
<Style TargetType="c:IconButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="c:IconButton">
<Grid Background="{TemplateBinding Background}" x:Name="ButtonBackground">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="IconTemplateContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="IconTemplateContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="IconTemplateContainer"
Template="{TemplateBinding IconTemplate}" />
<TextBlock VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Margin="{StaticResource PhoneHorizontalMargin}"
FontFamily="{StaticResource PhoneFontFamilyLight}"
Text="{TemplateBinding Text}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
So I could simply create the button like this and the appearance would be correct.
<c:IconButton Text="Some Text"
IconTemplate="{StaticResource IconsButtons.Sleepy}" />
The problem is that I want to change the Path's Stroke color when the user taps the button.
Since I'm going to use this button over and over again I thought that maybe it would be valuable to have another property that it would define the new stroke color when the button is tapped. Something like:
<c:IconButton Text="Some Text"
TappedColor="#123456" // New property
IconTemplate="{StaticResource IconsButtons.Sleepy}" />
But the problem is that I don't know how to change the color of the Path that is the Template (?) of the ContentControl. I was thinking about something like this:
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="(IconTemplateContainer).(Template).(Stroke)">
I know that this syntax is completely wrong but I wonder if someone can help me achieve my goal.
PS: I'm wrapping all the Paths in a ControlTemplate because using the Path directly and just binding it to the Content property of the ContentControl doesn't work on WP (or at least I'm not smart enough to make it work). Even in this case, how would I change a property of a object inside the ContentControls Contentfor a certainVisualState`?
UPDATE
The ControlTemplate code is as follows
<ControlTemplate x:Key="IconsButtons.Sleepy">
<Path Data="M32.000099,44.658999C36.566562,44.658999 39.162999,47.058804 ...."
Stretch="Uniform"
Fill="#FFFFFFFF"
Width="26"
Height="26"
Margin="0"
RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="1" ScaleY="1" />
</TransformGroup.Children>
</TransformGroup>
</Path.RenderTransform>
</Path>
</ControlTemplate>
You can do a TemplateBinding on the stroke color of the path to the foreground color of your IconButton. Then you can change the Foreground color of the IconButton and it will change the path color: Stroke="{TemplateBinding Foreground}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With