WPF Material Design Toggle Button

Another short post today, here I modified the code for my Apple Style Toggle Button so that it more resembled the MaterialDesign toggle button. I thought of this whilst playing with the YouTube autoplay button. Here is my code:

<Style TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Viewbox>
                    <Border x:Name="Border" CornerRadius="10"
                            Background="#FFE2E2E2"
                            Width="40" Height="20">
                        <Border.Effect>
                            <DropShadowEffect ShadowDepth="0.5" Direction="0" Opacity="0.3" />
                        </Border.Effect>
                        <Ellipse x:Name="Ellipse" Fill="#FF909090" Stretch="Uniform"
                                 Margin="-8 -4"
                                 Stroke="Gray" StrokeThickness="0.2"
                                 HorizontalAlignment="Stretch">
                            <Ellipse.Effect>
                                <DropShadowEffect BlurRadius="10" ShadowDepth="1" 
                                                  Opacity="0.3" Direction="260" />
                            </Ellipse.Effect>
                        </Ellipse>
                    </Border>
                </Viewbox>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="Checked">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Ellipse"
                                                    Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
                                                    To="#FF0069F3"
                                                    Duration="0:0:0.05"
                                                    AccelerationRatio="0.7"
                                                    DecelerationRatio="0.3"/>
                                <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                                    Storyboard.TargetProperty="Margin"
                                                    To="20 -4 -8 -4"
                                                    Duration="0:0:0.15" 
                                                    AccelerationRatio="0.7"
                                                    DecelerationRatio="0.3"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Unchecked">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Ellipse"
                                                    Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
                                                    To="#FF909090"
                                                    Duration="0:0:0.05" 
                                                    AccelerationRatio="0.7"
                                                    DecelerationRatio="0.3"/>
                                <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                                    Storyboard.TargetProperty="Margin"
                                                    To="-8 -4"
                                                    Duration="0:0:0.15"
                                                    AccelerationRatio="0.7"
                                                    DecelerationRatio="0.3"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And finally, here is a little GIF of the toggle button:

Enjoy!

Apple Style Toggle Button in WPF

A nice short post here, I wanted to share with you some code I recently used to create an Apple-style toggle button for WPF applications. I was quite surprised with how easy this was to make. Obviously it isn’t perfect but it makes do for my applications.

This is the style that I used:

<Style TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Viewbox>
                    <Border x:Name="Border" CornerRadius="10"
                            Background="#FFFFFFFF"
                            Width="40" Height="20">
                        <Border.Effect>
                            <DropShadowEffect ShadowDepth="0.5" Direction="0" Opacity="0.3" />
                        </Border.Effect>
                        <Ellipse x:Name="Ellipse" Fill="#FFFFFFFF" Stretch="Uniform"
                                 Margin="2 1 2 1"
                                 Stroke="Gray" StrokeThickness="0.2"
                                 HorizontalAlignment="Stretch">
                            <Ellipse.Effect>
                                <DropShadowEffect BlurRadius="10" ShadowDepth="1" Opacity="0.3" Direction="260" />
                            </Ellipse.Effect>
                        </Ellipse>
                    </Border>
                </Viewbox>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="Checked">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Border"
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    To="#FF4CD661"
                                                    Duration="0:0:0.1" />
                                <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                                        Storyboard.TargetProperty="Margin"
                                                        To="20 1 2 1"
                                                        Duration="0:0:0.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Unchecked">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Border"
                                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                                    To="White"
                                                    Duration="0:0:0.1" />
                                <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                                        Storyboard.TargetProperty="Margin"
                                                        To="2 1 2 1"
                                                        Duration="0:0:0.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Using this, I am able to have any size toggle button I want and it will still look the same. Thank goodness for view boxes! 🙌

Here is a little GIF showing the toggle button in action. I left it to just resize depending on the actual window to demonstrate it’s scalability:

Enjoy!

Using app.xaml and ResourceDictionaries for Cleaner WPF Customisation

When I first started making WPF forms, I was using PowerShell. This was a good starting point I think as I felt really comfortable with PowerShell which let me experiment more freely and break things in a way that I still felt comfortable.

However, this also meant putting all of my XAML into a single string. This might not sound too bad, but when you have five buttons all with slightly different templates and behaviours, the code quickly becomes messy and hard to read. Note that XAML is easy to read in the first place 😫 I was no stranger to having code that looked like this:

<Border Grid.Column="0" Grid.Row="1" Background="#FFE87E31" HorizontalAlignment="Right" Width="25" Height="25" Margin="0,0,2,0" CornerRadius="20"  BorderBrush="White" BorderThickness="1">
                <Label Name="Search_Button" Cursor="Hand" Foreground="White" Content="🔍" FontSize="12" Width="25" Height="27" Margin="-1.667,-1.667,-0.334,-0.334" />
            </Border>
<!-- OBJECT PANEL AND OBJECTS -->
            <Border HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="2" VerticalAlignment="Stretch" Background="#FF34495F" >
                <ScrollViewer VerticalScrollBarVisibility="Auto">
                    <StackPanel>
        <!-- ALL OPTION OBJECTS HERE -->
                        <Border Height="35">
                            <Border.Style>
                                <Style>
                                    <Setter Property="Border.Background" Value="#FF34495F"/>
                                    <Style.Triggers>
                                        <Trigger Property="Border.IsMouseOver" Value="True">
                                            <Setter Property="Border.Background" Value="#FF1F2A36" />
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>
                            <Label Name="General_Information_Button" Cursor="Hand" VerticalContentAlignment="Center" Foreground="White" Content="General Information" FontFamily="Century Gothic" FontSize="14" />
                        </Border>

Horrible I know…

But when I moved to use C# with WPF, I found that I could have separate resources that could be used by multiple controls at the same time. You do this by adding a resource dictionary to the app.xaml file inside the WPF project.

Here is a quick example of what I mean. I created a Styles folder in the root of my WPF project and added a new ResourceDictionary(WPF). I called this resource dictionary “TextStyles” and it looks like this:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="FontSize" Value="28"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="White"/>
    </Style>
</ResourceDictionary>

Perfect, I then added this to my app.xaml file which now looks like this:

<Application x:Class="WPFUI.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WPFUI">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Styles/TextStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

From now on, all the text blocks in the WPF application would use the Arial font, use font size 28, be bold and also be white.

Important Notes:

  1. It’s important to add your resource dictionaries to the app.xaml file in the correct order. You want to work from top to bottom. Meaning you don’t want a resource dictionary using something from another resource dictionary below it. For example, if you are using custom colours and want your text blocks to be that colour, you would put your colour resource first and then your text block resource.
  2. If you don’t want a resource to be used everywhere in your application if you style inside the resource dictionary a name. Then you can reference the style inside your WPF XAML code.

Enjoy!