WPF:重寫Slider滑動條模板,美化樣式設計
阿新 • • 發佈:2020-12-14
預設的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這樣的值呢。不知道有沒有人有簡單解決方法,歡迎交流!!!