RadioButton Template trong Windows 10 SplitView

Tại sao lại RadioButton?

Vì RadioButton đã hỗ trợ sẵn thuộc tính GroupName, bạn có thể gom nhóm các RadioButton. để có được các template mặc định cho các trạng thái focus/unfocus.

Một nút thông thường trong Hamburger Menu của Windows 10 bao gồm 1 icon bên trái và nội dung bên phải. Có thể dễ dàng sửa lại template của RadioButton cho hợp bằng Blend.

Hamburger Menu Item
Hamburger menu Item

Dùng Blend để xem template mặc định của RadioButton

Mở trang đang chứa RadioButton cần sửa bằng Blend như sau:

Design XAML page in Blend
Design XAML page in Blend

Blend sẽ có giao diện thế này (mỗi máy sẽ có cách hiển thị khác nhau).

Microsoft Blend for Visual Studio
Microsoft Blend for Visual Studio

Chú ý vào cửa sổ Objects and Timeline, sổ cây objects ra để tìm một RadioButton mà bạn muốn chỉnh sửa lại template.

Edit a copy of template
Edit a copy of template

Chỉnh sửa tên Style cho phù hợp, trong đó chọn Application thì Style này sẽ nằm torng Resource của cả App (trong App.xaml), ở đây mình chọn This Document để style này chỉ nằm trong file xaml hiện tại.

Create style resource
Create style resource

Blend sẽ sinh ra cho bạn 1 style dài thật dài, đây chính là style mặc định do Windows 10 định nghĩa cho mọi RadioButton.

RadioButton Visual State
RadioButton Visual State

Đây gọi là 1 trạng thái (State), và bên trong là 1 storyboard với các Target khác nhau. Như vậy, khi nhấn chuột, lần lượt các thuộc tính Stroke hay Fill của OuterEllipse, CheckOuterEllipse, CheckGlyph sẽ thay đổi thành giá trị mới.

Các trạng thái khác cũng được hiểu tương tự. Còn này là sắp xếp layout:

RadioButton design
RadioButton design

Chỗ này dễ hiểu nè, 1 Grid 2 column, column bên trái chứa 3 cái ellipse với tên đã thấy xuất hiện trên các state, thuộc tính bla bla bla. Túm lại nó là cái cục tròn tròn nằm trước cái RadioButton , 1 ContentPresenter nằm ở cột phải để hiển thị nội dung (ta không thay đổi phần này).

Sửa template

Vậy ta cần sửa những gì, đầu tiên là ta muốn bên cột trái không phải là 1 ellipse nữa mà là 1 icon.

Hô biến, xóa hết cái Grid chứa 3 cái Ellipse. Nếu đã xóa mấy cái ellipse rồi thì TargetName ở trên cũng vô nghĩa, xóa nốt các Animation nào xuất hiện tên các ellipse này. Nhớ chừa thẻ Storyboard ra nhé, vì vẫn cần dùng tới.

Khai báo thêm 3 Brush là 3 màu sẽ thay đổi cho 3 trạng thái Pressed, Checked, Hover. Các này tùy thích mỗi người mà chọn

<SolidColorBrush x:Key="MenuButtonPressedBackgroundBrush" Color="White" Opacity=0.3" />
<SolidColorBrush x:Key="MenuButtonCheckedBackgroundBrush" Color="White" Opacity=0.2" />
<SolidColorBrush x:Key="MenuButtonHoverBackgroundBrush" Color="White" Opacity=0.1" />

 

Dùng các Brush này vào các Animation, cuối cùng ta được bộ resource template mới cho RadioButton

<SolidColorBrush x:Key="MenuButtonPressedBackgroundBrush" Color="White" Opacity="0.3" />
<SolidColorBrush x:Key="MenuButtonCheckedBackgroundBrush" Color="White" Opacity="0.2" />
<SolidColorBrush x:Key="MenuButtonHoverBackgroundBrush" Color="White" Opacity="0.1" />
 
<Style x:Key="MenuRadioButtonStyle" TargetType="RadioButton">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
    <Setter Property="Padding" Value="8,6,0,0"/>
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
    <Setter Property="MinWidth" Value="30"/>
    <Setter Property="UseSystemFocusVisuals" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RadioButton">
                <Grid x:Name="BackgroundGrid" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MenuButtonHoverBackgroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MenuButtonPressedBackgroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled" />
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="CheckStates">
                            <VisualState x:Name="Checked">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundGrid">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MenuButtonCheckedBackgroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Unchecked"/>
                            <VisualState x:Name="Indeterminate"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
 
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="48"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
 
                    <FontIcon Glyph="{TemplateBinding Tag}" Margin="4,4,4,4" FontSize="24" VerticalAlignment="Center"/>
                    <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" TextWrapping="Wrap" VerticalAlignment="Center"/>
 
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

 

Ta cần dùng một thuộc tính chỉ định icon cần dùng, và không muốn viết một control khác chỉ vì thêm 1 thuộc tính. Do đó mình dùng Tag cho việc này. RadioButton sau cùng sẽ như thế này:

<RadioButton x:Name="MenuBtn" Click="MenuBtn_Click" Tag="" Content="Menu" GroupName="Menu" Style="{StaticResource MenuRadioButtonStyle}" Width="240" Height="40" FontSize="20"/>

 

Bảng mã của các icon và cách dùng FontIcon chi tiết nằm ở bài viết này

Hamburger menu item
Hamburger menu item

Code của phần này có thể xem ở đây

Vậy là xong 1 item trong hamburger menu. Hướng dẫn cách làm 1 Hamburger menu trong Windows 10 được trình bày ở bài viết này

Trao đổi thêm nhé

Website này sử dụng Akismet để hạn chế spam. Tìm hiểu bình luận của bạn được duyệt như thế nào.