WPF RadioButton/ToggleButton styling

I would like to mimic a style for a group of ToggleButtons as in the below image. Only one of the buttons can be "Checked" at any time.

My question is related to styling:

  • I'd like to have rounded corners on the leftmost button and the rightmost button as in the image but if there is a button between (like in the image), that should not have rounded corners. Sometimes there might only be two buttons to toggle.
  • I need style for different states: "Normal/Unchecked", "Mouseover", "Pressed" and "Checked" at the minimum.

The current control I am using for this is done like this:

<StackPanel Orientation="Horizontal" >
    <RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="All" Padding="12,8,12,8" GroupName="View"  />
    <RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Geolocated" Padding="12,8,12,8" GroupName="View" />
    <RadioButton Style="{StaticResource {x:Type ToggleButton}}" Content="Non Geolocated" Padding="12,8,12,8" GroupName="View" />
</StackPanel>

In the StackPanel Resources I am trying to set Style for ToggleButton but I'm pretty lost how to achieve the result as in the image above.

Answers


This may not be the easiest/best approach, but I took a stab at knocking up some ControlTemplates using Kaxaml, to produce something that looks like this:

You could store these templates in a ResourceDictionary and apply them when required, or use them if you were building your button list on the fly.

I actually created three slightly different styles, one for the left and right buttons, and one for the middle (you may be able to simplify this with extending/inheriting styles). Some repeated code omitted.

<Grid>
    <Grid.Resources>
        <!-- Brushes for colours/backgrounds -->
        <SolidColorBrush x:Key="FontBrush" Color="#DDDDDD"/>

        <LinearGradientBrush x:Key="BgBrush1" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#888888"/>
            <GradientStop Offset="1" Color="#222222"/>
        </LinearGradientBrush>

        <SolidColorBrush x:Key="BorderBrush1" Color="#333333"/>
        <LinearGradientBrush x:Key="CheckedBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#555555"/>
            <GradientStop Offset="1" Color="#111111"/>
        </LinearGradientBrush>

        <!-- Left Button Template -->
        <ControlTemplate x:Key="ToggleButtonLeft" TargetType="{x:Type ToggleButton}">
            <Border
                Name="Border"
                Background="{StaticResource BgBrush1}"
                BorderBrush="{StaticResource BorderBrush1}"
                BorderThickness="1"
                CornerRadius="5,0,0,5">
                <ContentPresenter
                    HorizontalAlignment="Center"
                    Margin="{TemplateBinding Padding}"
                    VerticalAlignment="Center"
                    Content="{TemplateBinding Content}"
                    TextBlock.FontWeight="Bold"
                    TextBlock.Foreground="{StaticResource FontBrush}"/>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="ToggleButton.IsMouseOver" Value="true">
                    <Setter TargetName="Border" Property="Background" Value="#808080"/>
                </Trigger>
                <Trigger Property="IsChecked" Value="true">
                    <Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedBrush}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

        <!-- Middle Button(s) Template -->
        <ControlTemplate x:Key="ToggleButtonMid" TargetType="{x:Type ToggleButton}">
            <Border
                Name="Border"
                Background="{StaticResource BgBrush1}"
                BorderBrush="{StaticResource BorderBrush1}"
                BorderThickness="0,1,0,1"
                CornerRadius="0" />
        <!-- Other code identical to Left Button Template -->       
        </ControlTemplate>

        <!-- Right Button Template -->
        <ControlTemplate x:Key="ToggleButtonRight" TargetType="{x:Type ToggleButton}">
            <Border
                Name="Border"
                Background="{StaticResource BgBrush1}"
                BorderBrush="{StaticResource BorderBrush1}"
                BorderThickness="1"
                CornerRadius="0, 5, 5, 0" />
        <!-- Other code identical to Left Button Template -->  
        </ControlTemplate>
    </Grid.Resources>

    <!-- Example Usage -->
    <Grid Background="#555555">
        <StackPanel Height="25" Orientation="Horizontal" Margin="5">
            <RadioButton Content="All" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonLeft}"/>
            <RadioButton Content="Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonMid}"/>
            <RadioButton Content="Non Geolocated" GroupName="View" Padding="2" Template="{DynamicResource ToggleButtonRight}"/>
        </StackPanel>
    </Grid>
</Grid>

You would have to add additional Triggers etc. for the IsPressed state, and any others required (e.g IsEnabled).


Need Your Help

Can I pass a number for varchar2 in Oracle?

sql oracle ora-01722

I have an Oracle table and a column (col1) has type varchar2(12 byte). It has one row and value of col1 is 1234

.NET: How do I determine if an object is a COM object?

.net com

How do I determine if an object is a COM object? I need to call Marshal.FinalReleaseComObject on all COM objects in an array of type Object.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.