Search code examples
wpfwpf-controls

Multiple styles for one custom control library


I wish to have one WPF Custom Control Library with multiple styles and to be able to access deferent style for deferent use.

For example

Assuming i have a project called IconButtonControl with one cs class file with all the needed dependencies, several .xaml files such: Blue.Generic.xaml, Green.Generic.xaml (and so on) in which they all referenced in the main Generic.xaml using <ResourceDictionary.MergedDictionaries>.

First style

<Style TargetType="{x:Type local:IconButton}" x:Key="BlueButton">
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="VerticalAlignment" Value="Bottom"/>
    <Setter Property="FlowDirection" Value="LeftToRight"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:IconButton}">
                <Grid Background="Transparent">
                    <Viewbox Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IconScale}">
                        <Path Name="PurplePath"
                                  Fill="{StaticResource LightBlueBrush}"
                                  Stretch="Fill"
                                  Data="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IconPath}"/>
                    </Viewbox>
                </Grid>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="MouseEnter">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                        <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource Blue}"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="MouseLeave">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                        <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource LightBlue}"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                    <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource DeepBlue}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonUp">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                    <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource Blue}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Second style

<Style TargetType="{x:Type local:IconButton}" x:Key="GreenButton">
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="VerticalAlignment" Value="Bottom"/>
    <Setter Property="FlowDirection" Value="LeftToRight"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:IconButton}">
                <Grid Background="Transparent">
                    <Viewbox Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IconScale}">
                        <Path Name="PurplePath"
                                  Fill="{StaticResource LightGreenBrush}" 
                                  Stretch="Fill"
                                  Data="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=IconPath}"/>
                    </Viewbox>
                </Grid>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="MouseEnter">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                        <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource Green}"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="MouseLeave">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                        <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource LightGreen}"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                    <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource DeepGreen}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonUp">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
                                    <LinearColorKeyFrame KeyTime="0:0:0:0.1" Value="{StaticResource Green}"/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And so on...

IconButton.cs

#region Dependency Properties

public static readonly DependencyProperty IconScaleProperty = DependencyProperty.Register(nameof(IconScale), typeof(double), typeof(IconButton), new PropertyMetadata(10.0));

public static readonly DependencyProperty IconPathProperty = DependencyProperty.Register(nameof(IconScale), typeof(Geometry), typeof(IconButton));

#endregion Dependency Properties

#region Properties

public double IconScale
{
    get => (double)GetValue(IconScaleProperty);
    set => SetValue(IconScaleProperty, value);
}

public Geometry IconPath
{
    get => (Geometry)GetValue(IconPathProperty);
    set => SetValue(IconPathProperty, value);
}

#endregion Properties

How can I use <IconButtonControl:IconButton> with GreenButton style for example?


Solution

  • If there is a property for setting the Style of the IconButton (which I assume is part of the template of the IconButtonControl) you could use this one:

    <local:IconButtonControl IconButtonStyle="{StaticResource GreenButton}" />
    

    If there is no such property like IconButtonStyle, you may be able to change the Style of the IconButton using an implicit Style:

    <local:IconButtonControl>
        <local:IconButtonControl.Resources>
            <Style TargetType="{x:Type local:IconButton}" BasedOn="{StaticResource GreenButton}" />
        </local:IconButtonControl.Resources>
    </local:IconButtonControl>
    

    Whether this works depends on how the template of the IconButtonControl is defined. If the template explicitly sets the Style of the IconButton, you will have to create a custom template for the entire IconButtonControl to be able to change the Style of the "inner" IconButton.