效果
<UserControl x:Class="WpfApp1.SilderArrange"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="UC_Arrange" Loaded="UC_Arrange_Loaded">
<StackPanel Orientation="Horizontal" Height="{Binding ElementName=UC_Arrange,Path=SilderHeight}" >
<TextBox Text="{Binding ElementName=SL_Bat1,Path=Value,Mode=TwoWay}"
KeyUp="TextBox_KeyUp1"
Width="35"
Margin="0,3" BorderBrush="CornflowerBlue" />
<Canvas Width="{Binding ElementName=UC_Arrange,Path=SilderWidth}" Margin="0,0,5,0">
<Slider Name="SL_Bat1"
Value="{Binding ElementName=UC_Arrange,Path=StartValue}"
Minimum="{Binding ElementName=UC_Arrange,Path=Minimum}"
Maximum="{Binding ElementName=UC_Arrange,Path=Maximum}"
SelectionStart="{Binding ElementName=UC_Arrange,Path=StartValue}"
SelectionEnd="{Binding ElementName=UC_Arrange,Path=EndValue}"
Width="{Binding ElementName=UC_Arrange,Path=SilderWidth}"
TickFrequency="{Binding ElementName=UC_Arrange,Path=SliderTickFrequency}"
FocusVisualStyle="{x:Null}"
IsSelectionRangeEnabled="True"
TickPlacement="BottomRight"
IsSnapToTickEnabled="True"
VerticalAlignment="Center"
Margin="2"
ValueChanged="SL_Bat1_ValueChanged">
<Slider.Clip>
<RectangleGeometry Rect="{Binding ElementName=UC_Arrange,Path=StartRect}" />
</Slider.Clip>
</Slider>
<Slider Name="SL_Bat2"
Value="{Binding ElementName=UC_Arrange,Path=EndValue}"
Minimum="{Binding ElementName=UC_Arrange,Path=Minimum}"
Maximum="{Binding ElementName=UC_Arrange,Path=Maximum}"
SelectionStart="{Binding ElementName=UC_Arrange,Path=StartValue}"
SelectionEnd="{Binding ElementName=UC_Arrange,Path=EndValue}"
Width="{Binding ElementName=UC_Arrange,Path=SilderWidth}"
TickFrequency="{Binding ElementName=UC_Arrange,Path=SliderTickFrequency}"
FocusVisualStyle="{x:Null}"
IsSelectionRangeEnabled="True"
TickPlacement="BottomRight"
IsSnapToTickEnabled="True"
VerticalAlignment="Center"
Margin="2"
ValueChanged="SL_Bat2_ValueChanged">
<Slider.Clip>
<RectangleGeometry Rect="{Binding ElementName=UC_Arrange,Path=EndRect}" />
</Slider.Clip>
</Slider>
</Canvas>
<TextBox KeyUp="TextBox_KeyUp2"
Text="{Binding ElementName=SL_Bat2,Path=Value,Mode=TwoWay}"
Width="35" Margin="0,3"
BorderBrush="CornflowerBlue"/>
</StackPanel>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// RangeControl.xaml 的交互逻辑
/// </summary>
public partial class SilderArrange : UserControl
{
#region 私有变量
private static int _width = 150; // 拖动条初始宽度
private static int _height = 30; // 高度
private static int _min = 0; // 最小值
private static int _max = 255; // 最大值
private static int _freq = 10; // 出现刻度的间距
#endregion
public SilderArrange()
{
InitializeComponent();
}
/// <summary>
/// 裁剪矩阵(头)
/// </summary>
private Rect StartRect
{
get
{
return (Rect)GetValue(StartRectProperty);
}
set
{
SetValue(StartRectProperty, value);
}
}
private static readonly DependencyProperty StartRectProperty =
DependencyProperty.Register("StartRect", typeof(Rect), typeof(SilderArrange));
/// <summary>
/// 裁剪矩阵(尾)
/// </summary>
private Rect EndRect
{
get { return (Rect)GetValue(EndRectProperty); }
set { SetValue(EndRectProperty, value); }
}
private static readonly DependencyProperty EndRectProperty =
DependencyProperty.Register("EndRect", typeof(Rect), typeof(SilderArrange));
#region 公开依赖属性
/// <summary>
/// 刻度间距,默认为10
/// </summary>
public int SliderTickFrequency
{
get { return (int)GetValue(SliderTickFrequencyProperty); }
set { SetValue(SliderTickFrequencyProperty, value); }
}
public static readonly DependencyProperty SliderTickFrequencyProperty =
DependencyProperty.Register("SliderTickFrequency", typeof(int), typeof(SilderArrange), new PropertyMetadata(_freq));
/// <summary>
/// 控件高度,默认为30
/// </summary>
public int SilderHeight
{
get { return (int)GetValue(SilderHeightProperty); }
set { SetValue(SilderHeightProperty, value); }
}
public static readonly DependencyProperty SilderHeightProperty =
DependencyProperty.Register("SilderHeight", typeof(int), typeof(SilderArrange), new PropertyMetadata(_height));
/// <summary>
/// 拖动条宽度,默认为150
/// </summary>
public int SilderWidth
{
get { return (int)GetValue(SilderWidthProperty); }
set { SetValue(SilderWidthProperty, value); }
}
public static readonly DependencyProperty SilderWidthProperty =
DependencyProperty.Register("SilderWidth", typeof(int), typeof(SilderArrange), new PropertyMetadata(_width));
/// <summary>
/// 最小值,默认为0
/// </summary>
public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(SilderArrange), new PropertyMetadata(_min));
/// <summary>
/// 最大值,默认为100
/// </summary>
public int Maximum
{
get { return (int)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(int), typeof(SilderArrange), new PropertyMetadata(_max));
/// <summary>
/// 选中开始值,默认为0
/// </summary>
public int StartValue
{
get { return (int)GetValue(StartValueProperty); }
set { SetValue(StartValueProperty, value); }
}
public static readonly DependencyProperty StartValueProperty =
DependencyProperty.Register("StartValue", typeof(int), typeof(SilderArrange));
/// <summary>
/// 选中结束值,默认为100
/// </summary>
public int EndValue
{
get { return (int)GetValue(EndValueProperty); }
set { SetValue(EndValueProperty, value); }
}
public static readonly DependencyProperty EndValueProperty =
DependencyProperty.Register("EndValue", typeof(int), typeof(SilderArrange), new PropertyMetadata(_max));
#endregion
#region 前台交互
/// <summary>
/// 对两个拖动条进行裁剪
/// </summary>
private void ClipSilder()
{
int selectedValue = EndValue - StartValue;
int totalValue = Maximum - Minimum;
double sliderClipWidth = SilderWidth * (StartValue - Minimum + selectedValue / 2) / totalValue;
// 对第一个拖动条进行裁剪
StartRect = new Rect(0, 0, sliderClipWidth, SilderHeight);
// 对第二个拖动条进行裁剪
EndRect = new Rect(sliderClipWidth, 0, SilderWidth, SilderHeight);
}
/// <summary>
/// 初始化裁剪
/// </summary>
private void UC_Arrange_Loaded(object sender, RoutedEventArgs e)
{
ClipSilder();
}
private void SL_Bat1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (e.NewValue > EndValue) // 检查值范围
StartValue = EndValue; // 超出,重设为最大值
ClipSilder();
}
private void SL_Bat2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (e.NewValue < StartValue)
EndValue = StartValue;
ClipSilder();
}
private void TextBox_KeyUp1(object sender, System.Windows.Input.KeyEventArgs e)
{
try
{
if (e.Key == Key.Enter) // 按回车时确认输入
StartValue = Convert.ToInt32(((TextBox)sender).Text);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void TextBox_KeyUp2(object sender, KeyEventArgs e)
{
try
{
if (e.Key == Key.Enter)
EndValue = Convert.ToInt32(((TextBox)sender).Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
}
}
使用
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:SilderArrange x:Name="SLA_V" SilderWidth="200" Minimum="0" Maximum="255"
HorizontalAlignment="Center"></local:SilderArrange>
</Grid>
</Window>
参考:
https://www.cnblogs.com/lekko/archive/2012/07/23/2604257.html