想要实现的效果
原生滑动条
需要认识一下滑动条的组成
具体的自定样式修改
SliderHorizontal样式
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TickBar x:Name="TopTick" Grid.Row="0" Height="4" Margin="0,0,0,2" Fill="{TemplateBinding Foreground}" Placement="Top" Visibility="Collapsed" /> <TickBar x:Name="BottomTick" Grid.Row="2" Height="4" Margin="0,2,0,0" Fill="{TemplateBinding Foreground}" Placement="Bottom" Visibility="Collapsed" /> <Border x:Name="TrackBackground" Grid.Row="1" Height="4.0" Margin="5,0" VerticalAlignment="center" Background="{StaticResource SliderThumb.Track.Border}" BorderBrush="{StaticResource SliderThumb.Track.Border}" BorderThickness="1"> <Canvas Margin="-6,-1"> <Rectangle x:Name="PART_SelectionRange" Height="4.0" Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" Visibility="Hidden" /> </Canvas> </Border> <Ellipse Grid.Row="1" Width="10" Height="10" Fill="Black" /> <Line Grid.Row="1" Grid.RowSpan="3" VerticalAlignment="Center" Fill="Purple" Stroke="Purple" StrokeThickness="3" X1="{Binding Path=LineX1, RelativeSource={RelativeSource TemplatedParent}}" X2="{Binding Path=LineX2, RelativeSource={RelativeSource TemplatedParent}}" Y1="0" Y2="0" /> <Track x:Name="PART_Track" Grid.Row="1"> <Track.DecreaseRepeatButton> <RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource RepeatButtonTransparent}" /> </Track.DecreaseRepeatButton> <Track.IncreaseRepeatButton> <RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource RepeatButtonTransparent}" /> </Track.IncreaseRepeatButton> <Track.Thumb> <Thumb x:Name="Thumb" Width="11" Height="18" VerticalAlignment="Center" Focusable="False" OverridesDefaultStyle="True" Template="{StaticResource SliderThumbHorizontalDefault}" /> </Track.Thumb> </Track> </Grid>
主要颜色距离的显示通过X1和X2的编辑显示距离
自定义控件CentreSlider
public class CentreSlider : Slider { protected override void OnValueChanged(double oldValue, double newValue) { base.OnValueChanged(oldValue, newValue); RefreshSlider(); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { base.OnRenderSizeChanged(sizeInfo); RefreshSlider(); } public double LineX1 { get { return (double)GetValue(LineX1Property); } set { SetValue(LineX1Property, value); } } public double LineX2 { get { return (double)GetValue(LineX2Property); } set { SetValue(LineX2Property, value); } } // Using a DependencyProperty as the backing store for LineX2. This enables animation, styling, binding, etc... public static readonly DependencyProperty LineX2Property = DependencyProperty.Register("LineX2", typeof(double), typeof(CentreSlider), new PropertyMetadata(0.0)); // Using a DependencyProperty as the backing store for LineX1. This enables animation, styling, binding, etc... public static readonly DependencyProperty LineX1Property = DependencyProperty.Register("LineX1", typeof(double), typeof(CentreSlider), new PropertyMetadata(0.0)); public void RefreshSlider() { //计算值和宽度的比例 var proportion = ActualWidth / Maximum; //起始点从中心点开始 LineX1 = ActualWidth / 2; //结束点值*比例 LineX2 = Value * Proportion; } }
最终效果