资讯详情

WPF中自定义双滑块Slider

当项目需要双滑块时,网上基本上可以是单滑块的样式和例子,但很少有双滑块。后来,我终于在网上找到了一个伟大的神的帖子。通过修改和改进,我终于满足了自己的需要,但后来我在查看代码时似乎不明白。现在我重新整理并记录下来,以备将来查看。

WPF中的Slider,看他的模板很复杂,粗略想想MultiRangeSlider只是几个滑块(Thumb),添加几个矩形,一个滑块对应两个矩形,当滑块移动时,不是两侧矩形宽度的变化,矩形我们只是想注意宽度的变化,不想调整他的实际位置,什么容器安装矩形,StackPanel,里面的对象总是首尾相连,但要做到Thumb能水平移动,在StackPanel中间显示不合适,然后放入Canvas然后使用这两个容器Grid叠在一起,Canvas在上面,就是这样。

<Grid>     <StackPanel Margin="15,0,15,0"                 x:Name="RangeContainer"                 Orientation="Horizontal">      </StackPanel>     <Canvas x:Name="ThumbContainer">     </Canvas> </Grid>

为了让滑块看起来好看,给滑块做个样式:

  <Style TargetType="local:ThumbEx">             <Setter Property="Width" Value="30"></Setter>             <Setter Property="Height" Value="100"></Setter>             <Setter Property="Template">                 <Setter.Value>                     <ControlTemplate TargetType="Thumb">                         <Grid>                             <StackPanel>                                 <Rectangle SnapsToDevicePixels="True"                                                                       Height="55"                                            RadiusX="1"                                            RadiusY="1"                                            StrokeThickness="10"                                            Stroke="#FF158BCF"                                            Fill="#FF158BCF"></Rectangle>                             </StackPanel>                         </Grid>                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>

在我自己的项目中,最终的目标是这样的:

所以代码更改后就是这样。

<UserControl.Background>         <ImageBrush ImageSource="1.png?x-oss-process=image/watermark,g_center,image_YXJ0aWNsZS9wdWJsaWMvd2F0ZXJtYXJrLnBuZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxQXzQwCg==,t_20"  Stretch="Uniform"/>     </UserControl.Background>     <UserControl.Resources>         <Style TargetType="local:ThumbEx">             <Setter Property="Width" Value="30"></Setter>             <Setter Property="Height" Value="100"></Setter>             <Setter Property="Template">                 <Setter.Value>                     <ControlTemplate TargetType="Thumb">                         <Grid>                             <StackPanel>                                 <Rectangle SnapsToDevicePixels="True"                                                                       Height="55"                                            RadiusX="1"                                            RadiusY="1"                                            StrokeThickness="10"                                            Stroke="#FF158BCF"                                            Fill="#FF158BCF"></Rectangle>                             </StackPanel>                         </Grid>                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>     </UserControl.Resources>     <Grid >         <StackPanel Margin="15,0,15,0"                                         x:Name="RangeContainer"                     Orientation="Horizontal">         </StackPanel>         <Canvas x:Name="ThumbContainer">         </Canvas>     </Grid>

为了方便多次使用,我们使用它UserControl当然,定义这个控件必须支持各种数据Binding啊,对于这个控制器,我不需要知道外部是什么样的数据结构,我只需要知道我需要显示多个滑块,所以必须有一个描述Range的数据结构

public class RangeItem {     #region 字段     private double _from;     private double _to;     private string _name;     private double _maxDuration;     private bool _isStatic;     private double _duration;      #endregion      #region 属性     public double From     {         get         {             return _from;         }         set         {             _from = value;         }     }      public double To     {         get         {             return _to;         }         set         {             _to = value;         }     }      /// <summary>     /// 是否静止     /// </summary>     public bool IsStatic     {         get         {             return _isStatic;         }         set         {             _isStatic = value;         }     }      public double Duration     {         get         {             return _duration;         }         set         {             _duration = value;         }     }      public double MaxDuration     {         get        {
            return _maxDuration;
        }
        set
        {
            _maxDuration = value;
        }
    }

    #endregion
}

重要的属性有From(起始值),To(结束值),MaxDuration(总长),

根据这一个数据,我们就能生成一个矩形。整个Slider的宽度是固定的,所以就可以根据(To-From)/MaxDuration*Slider长度,就能计算出这个矩形的宽度,直接加入StackPanel就行。

矩形加进去了,现在加滑块,因为滑块是在Canvas中的,所以他需要确切知道Canvas.Left附加属性,这个Left不就左边矩形的宽度么。在把滑块和左右两边的矩形关联起来,因为矩形的拖动事件需要实时去改变两边的矩形的宽度。

        private static double m_ThumbWidth;

        public void SetLeft(double length)
        {
            length = length / 100 * m_ThumbWidth - 15;
            Canvas.SetLeft(_thumbExs[0], length);
        }

        public void SetRight(double length)
        {
            length = length / 100 * m_ThumbWidth + 15;
            Canvas.SetRight(_thumbExs[1], length);
        }

要跟后端的数据绑定,也就是三个矩形的宽度关联

MultiSlider x:Name="mSlider" RangeItems="{Binding Items}"

下方就是加入滑块两端,也就是三个矩形的宽度

            #region 初始化滑块
            mSlider.ControlWidth = mSlider.Width;
            Items.Add(new RangeItem()
            {
                From = 0,
                To = 0,
                IsStatic = true,
                MaxDuration = 100
            });

            Items.Add(new RangeItem()
            {
                From = 0,
                To = 100,
                IsStatic = false,
                MaxDuration = 100
            });

            Items.Add(new RangeItem()
            {
                From = 100,
                To = 100,
                IsStatic = false,
                MaxDuration = 100
            });
            this.DataContext = this;
            #endregion

同时需要这段代码:

        #region 多滑块slider
        private ObservableCollection<RangeItem> _items = new ObservableCollection<RangeItem>();

        public ObservableCollection<RangeItem> Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
            }
        }
        #endregion

基本就这样,暂时满足自己的需求,时间长了回头过来写,有些啥意思自己都有点弄不明白了,凑合着看

标签: 襄樊滑竿电位器延安滑竿电位器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司