一個自定義的WPF滑塊按鈕


介紹

本文介紹了一個簡單的WPF雙狀態滑塊按鈕。每個狀態顯示的文本和滑塊按鈕的大小都可以從XAML中配置。

滑塊按鈕是使用依賴項屬性和模板資源的組合配置的。示例代碼包括三個模板資源,允許您創建以下內容:

    一個兩端為圓形、按鈕為圓形和標簽的滑塊控件一個末端為圓形、按鈕為圓形和標簽的滑塊控件一個末端為方形、按鈕為方形和標簽的滑塊控件

背景

我們的產品需要一個簡單的滑塊按鈕,由於微軟沒有提供一個標准的滑塊按鈕,我不得不編寫一個自定義控件。網上有很多例子,但大多數如果不是全部趨向於硬編碼的外觀。因此顏色是固定的,文本是固定的,或者大小是固定的。更靈活的往往是相當復雜的。我們想要更靈活的外觀,包括由XAML代碼中的屬性控制的大小(寬度和高度)。一個關鍵的需求是代碼要盡可能簡單,這確保了它容易理解,並且在需要時易於擴展以滿足您自己的需要。我本可以使它更加靈活,但當前的版本可以滿足我的所有要求。

理想情況下,您應該熟悉依賴項屬性、資源字典和控制模板的基礎知識。然而,即使您的知識有限,您也應該能夠弄清楚如何使用代碼,並且能夠做出簡單的更改來滿足您自己的需求。

截圖

演示應用程序包括所有三種風格的示例:

Image 1

Image 2

使用的代碼

SliderControl派生自標准的WPF ToggleButton類。它添加了三個依賴屬性:

按鈕寬度滑塊按鈕的寬度當按鈕被設置為on位置時要顯示的文本將按鈕設置為off位置時要顯示的文本加貼標簽

按鈕的整體寬度由基控件的width屬性控制。高度由ButtonWidth自定義屬性控制。

有三種樣式,定義了三種形式的滑塊按鈕:

左邊有標簽的滑塊按鈕一個帶有圓形按鈕的滑塊按鈕一個帶有矩形按鈕的滑塊按鈕

每個滑塊按鈕樣式都定義一個模板,該模板覆蓋控件的外觀。每個滑塊按鈕都由使用網格控件對齊的橢圓、邊框和標簽控件組合而成。觸發器用於在按鈕被選中和未選中時顯示和隱藏組件控件。

SliderButton類

SliderButton類派生自標准的ToggleButton類,並添加了三個依賴屬性:

namespace WpfSliderButtonDemo.View
{
    public class SliderButton : System.Windows.Controls.Primitives.ToggleButton
    {
        public double ButtonWidth
        {
            get
            {
                return (double)GetValue(ButtonWidthProperty);
            }
            set
            {
                SetValue(ButtonWidthProperty, value);
            }
        }

        public static readonly System.Windows.DependencyProperty ButtonWidthProperty = 
               System.Windows.DependencyProperty.Register("ButtonWidth", typeof(double), 
               typeof(SliderButton), new System.Windows.PropertyMetadata(0.0));

        public string OnLabel
        {
            get
            {
                return (string)GetValue(OnLabelProperty);
            }
            set
            {
                SetValue(OnLabelProperty, value);
            }
        }

        public static readonly System.Windows.DependencyProperty 
               OnLabelProperty = System.Windows.DependencyProperty.Register
               ("OnLabel", typeof(string), typeof(SliderButton), 
               new System.Windows.PropertyMetadata(""));

        public string OffLabel
        {
            get
            {
                return (string)GetValue(OffLabelProperty);
            }
            set
            {
                SetValue(OffLabelProperty, value);
            }
        }

        public static readonly System.Windows.DependencyProperty OffLabelProperty = 
               System.Windows.DependencyProperty.Register("OffLabel", typeof(string), 
               typeof(SliderButton), new System.Windows.PropertyMetadata(""));
    }
}

styleSliderButton風格

styleSliderButton樣式定義了一個帶有圓形按鈕的滑塊按鈕和滑塊軌跡上的標簽:

<Stylex:Key="styleSliderButton"TargetType="{x:Type local:SliderButton}">
    <SetterProperty="Template">
        <Setter.Value>
            <ControlTemplateTargetType="{x:Type local:SliderButton}">
                <Gridx:Name="mainGrid">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinitionWidth="Auto"/>
                    </Grid.ColumnDefinitions>
                    <BorderGrid.Column="0"Name="_borderOn"Background="Transparent"Width="{TemplateBinding Width}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinitionHeight="Auto"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="*"/>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="Auto"/>
                            </Grid.ColumnDefinitions>
                            <EllipseGrid.Row="0"Grid.RowSpan="1"Grid.Column="0"Grid.ColumnSpan="2"Width="{TemplateBinding ButtonWidth}"Height="{TemplateBinding ButtonWidth}"Style="{StaticResource styleEllipseGreyButton}"Panel.ZIndex="3"/>
                            <BorderGrid.Row="0"Grid.RowSpan="1"Grid.Column="1"Grid.ColumnSpan="3"Background="ForestGreen"BorderBrush="Gray"BorderThickness="0,1,0,1"Panel.ZIndex="1"/>
                            <LabelGrid.Row="0"Grid.RowSpan="1"Grid.Column="2"Grid.ColumnSpan="3"Name="_labelOn"Content="{TemplateBinding OnLabel}"SPanel.ZIndextyle=
                                 "{StaticResource styleSliderButtonLabel}"="2"/>
                            <EllipseGrid.Row="0"Grid.RowSpan="1"Grid.Column="3"Grid.ColumnSpan="2"Width="{TemplateBinding ButtonWidth}"Height="{TemplateBinding ButtonWidth}"Style="{StaticResource styleEllipseButton}"Fill="ForestGreen"Panel.ZIndex="0"/>
                        </Grid>
                    </Border>

                    <BorderGrid.Column="0"Name="_borderOff"Background="Transparent"Width="{TemplateBinding Width}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinitionHeight="Auto"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="*"/>
                                <ColumnDefinitionWidth="Auto"/>
                                <ColumnDefinitionWidth="Auto"/>
                            </Grid.ColumnDefinitions>
                            <EllipseGrid.Row="0"Grid.RowSpan="1"Grid.Column="0"Grid.ColumnSpan="2"Width="{TemplateBinding ButtonWidth}"Height="{TemplateBinding ButtonWidth}"VerticalAlignment="Stretch"Fill="Crimson"Stroke="Gray"Panel.ZIndex="0"/>
                            <LabelGrid.Row="0"Grid.RowSpan="1"Grid.Column="0"Grid.ColumnSpan="3"Name="_labelOff"Content="{TemplateBinding OffLabel}"Style="{StaticResource styleSliderButtonLabel}"Panel.ZIndex="2"/>
                            <BorderGrid.Row="0"Grid.RowSpan="1"Grid.Column="1"Grid.ColumnSpan="3"Background="Crimson"BorderBrush="Gray"BorderThickness="0,1,0,1"Panel.ZIndex="1"/>
                            <EllipseGrid.Row="0"Grid.RowSpan="1"Grid.Column="3"Grid.ColumnSpan="2"Width="{TemplateBinding ButtonWidth}"Height="{TemplateBinding ButtonWidth}"Style="{StaticResource styleEllipseGreyButton}"Panel.ZIndex="3"/>
                        </Grid>
                    </Border>
                </Grid>

                <!-- triggers toggle visual appearance -->
                <ControlTemplate.Triggers>
                    <TriggerProperty="IsChecked"Value="True">
                        <SetterTargetName="_borderOff"Property="Visibility"Value="Collapsed"/>
                        <SetterTargetName="_borderOn"Property="Visibility"Value="Visible"/>
                    </Trigger>
                    <TriggerProperty="IsChecked"Value="False">
                        <SetterTargetName="_borderOff"Property="Visibility"Value="Visible"/>
                        <SetterTargetName="_borderOn"Property="Visibility"Value="Collapsed"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

樣式覆蓋定義控件的外觀和行為的Template屬性。控件由包含兩個復合元素的網格構造,其中一個元素在選中控件時顯示,另一個元素在選中控件時顯示。每個復合元素由帶有橢圓、邊框和標簽子元素的網格組成,這些子元素共同創建了滑塊控件的外觀。

注意面板的使用。附加屬性以允許滑塊按鈕橢圓出現在軌道前面,而軌道出現在表示軌道末端的橢圓前面。

還要注意TemplateBinding標記擴展的使用,它允許模板中的元素使用在模板化控件上定義的屬性,即。包括在ToggleButton控件類上定義的屬性。

滑塊按鈕是使用一個帶有styleEllipseGreyButton樣式的橢圓元素創建的:

<Stylex:Key="styleEllipseGreyButton"TargetType="{x:Type Ellipse}"BasedOn="{StaticResource styleEllipseButton}">
    <SetterProperty="Fill">
        <Setter.Value>
            <LinearGradientBrushEndPoint="0.504,1.5"StartPoint="0.504,0.03">
                <GradientStopColor="#FFFFFF"Offset="0"/>
                <GradientStopColor="#BBBBBB"Offset="0.567"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

標簽文本的外觀使用styleSliderButtonLabel樣式定義:

<Stylex:Key="styleSliderButtonLabel"TargetType="{x:Type Label}">
    <SetterProperty="Background"Value="Transparent"/>
    <SetterProperty="Foreground"Value="White"/>
    <SetterProperty="BorderThickness"Value="1"/>
    <SetterProperty="VerticalAlignment"Value="Center"/>
    <SetterProperty="HorizontalAlignment"Value="Center"/>
    <SetterProperty="HorizontalContentAlignment"Value="Center"/>
    <SetterProperty="Padding"Value="0"/>
</Style>

使用控制

添加自定義滑塊控件到一個視圖非常容易:

<view:SliderButtonGrid.Row="7"Grid.Column="1"OnLabel="On"OffLabel="Off"Width="110"ButtonWidth="50"Style="{StaticResource styleSliderButton}"HorizontalAlignment="Center"IsChecked="{Binding IsEnabled}"FontSize="30"/>

樣例應用程序

我提供了一個簡單的演示應用程序,您可以下載。它包括滑塊按鈕的代碼,以及一個主窗口,其中包含使用所提供的樣式的大量示例滑塊按鈕。

進一步增強

未來的增強包括創建垂直滑塊按鈕,以及添加依賴屬性來控制兩種狀態的背景顏色。這些任務留給讀者作為練習。

錯誤

我無法使標簽文本垂直居中。這並不明顯,但理想情況下應該得到解決。

的興趣點

WPF非常靈活,有很多方法可以使用標准控件創建切換按鈕的錯覺。

歷史

  • 2019年4月24日:第一版

本文轉載於:http://www.diyabc.com/frontweb/news13544.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM