WPF中实现含有中心点Slider双向滑动条

想要实现的效果

原生滑动条

需要认识一下滑动条的组成

  • 在原生控件中生成“资源字典”对应的样式
  • 然后在track所在的列进行添砖加瓦
  • 由于track在row="1"的位置,只需要在这个位置上面添加一个Ellipse和Line
  • Ellipse是来描述固定在滑动条上的中心点的位置
  • line是来描述Thumb从中心点移动到其他位置显示的颜色

具体的自定样式修改

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的编辑显示距离

  • 所以需要将这里的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;
        }
    }

最终效果

posted @ 2023-06-09 14:03  庆喜  阅读(332)  评论(0编辑  收藏  举报