1. 程式人生 > 其它 >WPF:重寫Slider滑動條模板,美化樣式設計

WPF:重寫Slider滑動條模板,美化樣式設計

技術標籤:WPFwpfui

預設的Slider

看一下預設的Slider樣式

<Style x:Key="BaseSliderStyle" TargetType="Slider">
    <Setter Property="Width" Value="500"/>
    <Setter Property="Margin" Value="20"/>
    <Setter Property="Maximum" Value="10"
/> <Setter Property="IsSnapToTickEnabled" Value="True"/> <Setter Property="TickPlacement" Value="Both"/> <Setter Property="TickFrequency" Value="1"/> <Setter Property="SnapsToDevicePixels" Value="True"
/>
</Style>

在這裡插入圖片描述
設定了最大值是10,上下的Tick指標都顯示,間隔是1。
上圖從上往下分析一下結構就是:上TickBar + 包含Thumb、RepeatButton的Track + 下TickBar,即
在這裡插入圖片描述
MSDN上面是這樣的:
在這裡插入圖片描述

RepeatButton就是點選Thumb兩側空白(實際是RepeatButton背景色是透明色)的實現移動Thumb的效果。

重新設計Slider

由上面的結構分析,不難寫出Template樣式

<Style x:Key="DefaultSliderStyle" TargetType="Slider"
BasedOn="{StaticResource BaseSliderStyle}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Slider"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TickBar Name="TopTick" Grid.Row="0" Placement="Top" Height="4" Visibility="Visible" Fill="Red"/> <Border Name="TrackBackground" Grid.Row="1" Height="4" Background="Green"/> <Track Name="PART_Track" Grid.Row="1"> <Track.DecreaseRepeatButton> <RepeatButton Style="{StaticResource DefaultRepeatButtonStyle}" Command="Slider.DecreaseLarge"/> </Track.DecreaseRepeatButton> <Track.Thumb> <Thumb Style="{StaticResource DefaultSliderThumbStyle}"/> </Track.Thumb> <Track.IncreaseRepeatButton> <RepeatButton Style="{StaticResource DefaultRepeatButtonStyle}" Command="Slider.IncreaseLarge"/> </Track.IncreaseRepeatButton> </Track> <TickBar Name="BottomTick" Grid.Row="2" Placement="Bottom" Height="4" Visibility="Visible" Fill="Red"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>

模板包括三行,分別放上TickBar、Track、下TickBar

1、用一個Border做背景色;
2、TickBar都設定了可見(為了演示),一開始可設定都不可見;然後新增Trigger,判斷TickPlacement的值取設定那個可見;
3、Thumb 是一個圓形按鈕;
4、RepeatButton設定成透明;
5、Track的Name一定要設定為PART_Track,不然就不能拖動Thumb了。(在其他地方看到的解釋了,微軟寫內部模板,這類命名方式不能改,個人經驗是類似PART_XXX這類名稱。)

Thumb的樣式是,一個圓:

<Style x:Key="DefaultSliderThumbStyle" TargetType="Thumb">
    <Setter Property="Width" Value="15"/>
    <Setter Property="Height" Value="15"/>
    <Setter Property="Background" Value="Blue"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Thumb">
                <Ellipse Width="{TemplateBinding Width}" 
                         Height="{TemplateBinding Height}"
                         Fill="{TemplateBinding Background}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

RepeateButton透明:

<Style x:Key="DefaultRepeatButtonStyle" TargetType="RepeatButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RepeatButton">
                <Border Background="Transparent"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

效果圖:

在這裡插入圖片描述

美化Slider

樣式:

<Window.Resources>
    <DropShadowEffect x:Key="UnhoverThumbEffect" BlurRadius="5" ShadowDepth="0" Opacity="0.3" Color="RoyalBlue"/>
    <DropShadowEffect x:Key="HoverThumbEffect" BlurRadius="5" ShadowDepth="0" Opacity="0.5" Color="RoyalBlue"/>
    <DropShadowEffect x:Key="DragThumbEffect" BlurRadius="8" ShadowDepth="0" Opacity="1" Color="RoyalBlue"/>
    <Style x:Key="DefaultSliderThumbStyle" TargetType="Thumb">
        <Setter Property="Width" Value="15"/>
        <Setter Property="Height" Value="15"/>
        <Setter Property="Background" Value="White"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Thumb">
                    <Ellipse Width="{TemplateBinding Width}" 
                             Height="{TemplateBinding Height}"
                             Fill="{TemplateBinding Background}"
                             Effect="{StaticResource UnhoverThumbEffect}">
                    </Ellipse>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Effect" Value="{StaticResource HoverThumbEffect}"/>
                            <Setter Property="Cursor" Value="Hand"/>
                        </Trigger>
                        <Trigger Property="IsDragging" Value="True">
                            <Setter Property="Effect" Value="{StaticResource DragThumbEffect}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DefaultLeftRepeatButtonStyle" TargetType="RepeatButton">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="RepeatButton">
                	<Border Background="RoyalBlue" Height="4"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DefaultRightRepeatButtonStyle" TargetType="RepeatButton">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="RepeatButton">
                    <Border Background="Transparent"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="BaseSliderStyle" TargetType="Slider">
        <Setter Property="Width" Value="500"/>
        <Setter Property="MinHeight" Value="30"/>
        <Setter Property="Margin" Value="20"/>
        <Setter Property="Maximum" Value="100"/>
        <Setter Property="IsSnapToTickEnabled" Value="True"/>
        <!--移到滑鼠點選的指定刻度點-->
        <Setter Property="IsMoveToPointEnabled" Value="True"/>
        <!--移動的最大最小距離。
            由於設定了IsMoveToPointEnabled=True,下面兩個屬性就沒發揮作用了。
            點選RepeatButton時直接就移動到了指定位置。
            如果為False,那麼由於RepeatButton綁定了Slider.DecreaseLarge命令,
            那點選左右的RepeatButton一次,就移動10個單位距離。
            同樣的還有Slider.DecreaseSmall命令,移動1個單位距離-->
        <Setter Property="LargeChange" Value="10"/>
        <Setter Property="SmallChange" Value="1"/>
        <Setter Property="Background" Value="LightGray"/>
        <Setter Property="Foreground" Value="RoyalBlue"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
    </Style>
    <Style x:Key="BeautifySliderStyle" TargetType="Slider" BasedOn="{StaticResource BaseSliderStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Slider">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition MinHeight="{TemplateBinding MinHeight}" Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <TickBar Name="TopTick"
                                 Grid.Row="0"
                                 Placement="Top"
                                 Height="4"
                                 Visibility="Collapsed"
                                 Fill="{TemplateBinding Foreground}"/>
                        <Border Name="TrackBackground" 
                                Grid.Row="1"
                                Height="4"
                                Background="{TemplateBinding Background}"/>
                        <Track Name="PART_Track" Grid.Row="1">
                            <Track.DecreaseRepeatButton>
                                <RepeatButton Style="{StaticResource DefaultLeftRepeatButtonStyle}" Command="Slider.DecreaseLarge"/>
                            </Track.DecreaseRepeatButton>
                            <Track.Thumb>
                                <Thumb Style="{StaticResource DefaultSliderThumbStyle}"/>
                            </Track.Thumb>
                            <Track.IncreaseRepeatButton>
                                <RepeatButton Style="{StaticResource DefaultRightRepeatButtonStyle}" Command="Slider.IncreaseLarge"/>
                            </Track.IncreaseRepeatButton>
                        </Track>
                        <TickBar Name="BottomTick"
                                 Grid.Row="2"
                                 Placement="Bottom"
                                 Height="4"
                                 Visibility="Collapsed"
                                 Fill="{TemplateBinding Foreground}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="TickPlacement" Value="Both">
                            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="TickPlacement" Value="BottomRight">
                            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="TickPlacement" Value="TopLeft">
                            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid Background="White">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center">
        <Slider Style="{StaticResource BaseSliderStyle}"/>
        <Slider Name="slider" Style="{StaticResource BeautifySliderStyle}" TickPlacement="BottomRight"/>
        <TextBlock Text="{Binding ElementName=slider, Path=Value}"/>
    </StackPanel>
</Grid>

效果圖:
在這裡插入圖片描述

有個問題

我不想要下面那共101個刻度線,我只想要11個代表0、10、20、30、40、50、60、70、80、90、100的刻度線就行了。雖然可以設定

<Setter Property="TickFrequency" Value="10"/>
或者
<Setter Property="Ticks" Value="0,10,20,30,40,50,60,70,80,90,100"/>

但是,此時移動一次的最小單位距離就不是1了,而是10。可我還是希望最小移動單位是1,不然怎麼得到如63這樣的值呢。不知道有沒有人有簡單解決方法,歡迎交流!!!