问题
I want to create range slider in UWP. I didn't find any example. There are only single sliders but I want it like
Does anybody know how can i do it? Please help me.
回答1:
To create a range slider in UWP, we can create a custom control or use UserControl. Here I use UserControl
for example:
Firstly, I add a UserControl named "MyRangeSlider" in my project.
In the XAML:
<UserControl x:Class="UWP.MyRangeSlider"
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:local="using:UWP"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid Height="32" Margin="8,0">
<Grid.Resources>
<Style TargetType="Thumb">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Ellipse Width="32"
Height="32"
Fill="White"
RenderTransformOrigin="0.5 0.5"
Stroke="Gray"
StrokeThickness="1">
<Ellipse.RenderTransform>
<TranslateTransform X="-16" />
</Ellipse.RenderTransform>
</Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Rectangle Height="16"
Margin="8,0"
Fill="#FFD5D5D5"
RadiusX="5"
RadiusY="5" />
<Canvas x:Name="ContainerCanvas" Margin="8,0" SizeChanged="ContainerCanvas_SizeChanged">
<Thumb x:Name="MinThumb" DragCompleted="MinThumb_DragCompleted" DragDelta="MinThumb_DragDelta" />
<Thumb x:Name="MaxThumb" DragCompleted="MaxThumb_DragCompleted" DragDelta="MaxThumb_DragDelta" />
<Rectangle x:Name="ActiveRectangle"
Canvas.Top="8"
Height="16"
Canvas.ZIndex="-1"
Fill="#FF69A0CC" />
</Canvas>
</Grid>
</UserControl>
And in its code-behind:
public sealed partial class MyRangeSlider : UserControl
{
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public double RangeMin
{
get { return (double)GetValue(RangeMinProperty); }
set { SetValue(RangeMinProperty, value); }
}
public double RangeMax
{
get { return (double)GetValue(RangeMaxProperty); }
set { SetValue(RangeMaxProperty, value); }
}
public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(MyRangeSlider), new PropertyMetadata(0.0));
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(MyRangeSlider), new PropertyMetadata(1.0));
public static readonly DependencyProperty RangeMinProperty = DependencyProperty.Register("RangeMin", typeof(double), typeof(MyRangeSlider), new PropertyMetadata(0.0, OnRangeMinPropertyChanged));
public static readonly DependencyProperty RangeMaxProperty = DependencyProperty.Register("RangeMax", typeof(double), typeof(MyRangeSlider), new PropertyMetadata(1.0, OnRangeMaxPropertyChanged));
public MyRangeSlider()
{
this.InitializeComponent();
}
private static void OnRangeMinPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var slider = (MyRangeSlider)d;
var newValue = (double)e.NewValue;
if (newValue < slider.Minimum)
{
slider.RangeMin = slider.Minimum;
}
else if (newValue > slider.Maximum)
{
slider.RangeMin = slider.Maximum;
}
else
{
slider.RangeMin = newValue;
}
if (slider.RangeMin > slider.RangeMax)
{
slider.RangeMax = slider.RangeMin;
}
slider.UpdateMinThumb(slider.RangeMin);
}
private static void OnRangeMaxPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var slider = (MyRangeSlider)d;
var newValue = (double)e.NewValue;
if (newValue < slider.Minimum)
{
slider.RangeMax = slider.Minimum;
}
else if (newValue > slider.Maximum)
{
slider.RangeMax = slider.Maximum;
}
else
{
slider.RangeMax = newValue;
}
if (slider.RangeMax < slider.RangeMin)
{
slider.RangeMin = slider.RangeMax;
}
slider.UpdateMaxThumb(slider.RangeMax);
}
public void UpdateMinThumb(double min, bool update = false)
{
if (ContainerCanvas != null)
{
if (update || !MinThumb.IsDragging)
{
var relativeLeft = ((min - Minimum) / (Maximum - Minimum)) * ContainerCanvas.ActualWidth;
Canvas.SetLeft(MinThumb, relativeLeft);
Canvas.SetLeft(ActiveRectangle, relativeLeft);
ActiveRectangle.Width = (RangeMax - min) / (Maximum - Minimum) * ContainerCanvas.ActualWidth;
}
}
}
public void UpdateMaxThumb(double max, bool update = false)
{
if (ContainerCanvas != null)
{
if (update || !MaxThumb.IsDragging)
{
var relativeRight = (max - Minimum) / (Maximum - Minimum) * ContainerCanvas.ActualWidth;
Canvas.SetLeft(MaxThumb, relativeRight);
ActiveRectangle.Width = (max - RangeMin) / (Maximum - Minimum) * ContainerCanvas.ActualWidth;
}
}
}
private void ContainerCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
var relativeLeft = ((RangeMin - Minimum) / (Maximum - Minimum)) * ContainerCanvas.ActualWidth;
var relativeRight = (RangeMax - Minimum) / (Maximum - Minimum) * ContainerCanvas.ActualWidth;
Canvas.SetLeft(MinThumb, relativeLeft);
Canvas.SetLeft(ActiveRectangle, relativeLeft);
Canvas.SetLeft(MaxThumb, relativeRight);
ActiveRectangle.Width = (RangeMax - RangeMin) / (Maximum - Minimum) * ContainerCanvas.ActualWidth;
}
private void MinThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
var min = DragThumb(MinThumb, 0, Canvas.GetLeft(MaxThumb), e.HorizontalChange);
UpdateMinThumb(min, true);
RangeMin = Math.Round(min);
}
private void MaxThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
var max = DragThumb(MaxThumb, Canvas.GetLeft(MinThumb), ContainerCanvas.ActualWidth, e.HorizontalChange);
UpdateMaxThumb(max, true);
RangeMax = Math.Round(max);
}
private double DragThumb(Thumb thumb, double min, double max, double offset)
{
var currentPos = Canvas.GetLeft(thumb);
var nextPos = currentPos + offset;
nextPos = Math.Max(min, nextPos);
nextPos = Math.Min(max, nextPos);
return (Minimum + (nextPos / ContainerCanvas.ActualWidth) * (Maximum - Minimum));
}
private void MinThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
UpdateMinThumb(RangeMin);
Canvas.SetZIndex(MinThumb, 10);
Canvas.SetZIndex(MaxThumb, 0);
}
private void MaxThumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
UpdateMaxThumb(RangeMax);
Canvas.SetZIndex(MinThumb, 0);
Canvas.SetZIndex(MaxThumb, 10);
}
}
Then I can use MyRangeSlider
like following:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBox HorizontalAlignment="Center" FontSize="20" Text="{Binding RangeMin, ElementName=RangeSlider, Mode=TwoWay}" />
<local:MyRangeSlider x:Name="RangeSlider"
Grid.Column="1"
Maximum="100"
Minimum="0"
RangeMax="80"
RangeMin="20" />
<TextBox Grid.Column="2"
HorizontalAlignment="Center"
FontSize="20"
Text="{Binding RangeMax,
ElementName=RangeSlider,
Mode=TwoWay}" />
</Grid>
And it looks like:
This is a simple sample, you can edit it to meet your requirement. And if you want to create a custom control, you can refer to Building a custom control using XAML and C#. Although this article is for Windows 8 XAML platform, but UWP is the same.
来源:https://stackoverflow.com/questions/36545896/universal-windows-uwp-range-slider