我创建了一个RangeSlider控件: XAML:
<Style x:Key="RangeSliderRepeatButton" TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" Height="6" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RangeSliderThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid Margin="0,0,0,10">
<Label x:Name="PART_ValueOfSlider" Content="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"
Margin="0 -20 0 0"
HorizontalAlignment="Center"
Foreground="Red"/>
<Path x:Name="PART_Rectangle" Fill="Gray">
<Path.Data>
<RectangleGeometry Rect="0,0 10 9" RadiusX="2" RadiusY="2"></RectangleGeometry>
</Path.Data>
<Path.Effect>
<DropShadowEffect ShadowDepth="2" BlurRadius="3" Color="Black" Opacity="0.4" Direction="270" />
</Path.Effect>
</Path>
<Path x:Name="PART_Traingle" Data="M 0 8 L 5 14 L 10 8 Z" Fill="Gray" >
<Path.Effect>
<DropShadowEffect ShadowDepth="1" BlurRadius="0" Color="Black" Opacity="0.4" Direction="270" />
</Path.Effect>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Rectangle" Property="Fill" Value="{DynamicResource LabledSliderThumbHoverBrush}" />
<Setter TargetName="PART_Traingle" Property="Fill" Value="{DynamicResource LabledSliderThumbHoverBrush}" />
</Trigger>
<Trigger Property="IsMouseCaptured" Value="True">
<Setter TargetName="PART_Rectangle" Property="Fill" Value="{DynamicResource LabledSliderThumbFocusesBrush}" />
<Setter TargetName="PART_Traingle" Property="Fill" Value="{DynamicResource LabledSliderThumbFocusesBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RangeSlider" TargetType="{x:Type Slider}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Slider}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="{TemplateBinding MinWidth}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Track Grid.Column="0" x:Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource RangeSliderRepeatButton}" Command="Slider.DecreaseLarge" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="PART_Thumb" Style="{StaticResource RangeSliderThumbStyle}"/>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource RangeSliderRepeatButton}" Command="Slider.IncreaseLarge" />
</Track.IncreaseRepeatButton>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Grid x:Name="LayoutRoot" Background="#FF878889">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="353*"/>
</Grid.ColumnDefinitions>
<Border VerticalAlignment="Center"
BorderBrush="Black"
Background="Black"
Height="10"
Grid.Column="0"
BorderThickness="1"
Padding="2"
CornerRadius="4" Grid.ColumnSpan="2" Margin="0,5"/>
<Border x:Name="progressBorder"
SnapsToDevicePixels="True"
Background="Blue"
BorderBrush="Blue"
Height="6"
VerticalAlignment="Center" Grid.ColumnSpan="2" Margin="0,7"
/>
<Slider x:Name="LowerSlider"
Minimum="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=Minimum, Mode=TwoWay}"
Maximum="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=Maximum, Mode=TwoWay}"
Value="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=LowerValue, Mode=TwoWay}"
Style="{StaticResource SliderStyle}" Grid.ColumnSpan="2" />
<Slider x:Name="UpperSlider"
Minimum="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=Minimum, Mode=TwoWay}"
Maximum="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=Maximum, Mode=TwoWay}"
Value="{Binding RelativeSource={RelativeSource AncestorType=local:RangeSlider}, Path=UpperValue, Mode=TwoWay}"
Style="{StaticResource SliderStyle}" Grid.Column="1" />
</Grid>
RangeSlider.cs
public partial class RangeSlider : UserControl
{
public RangeSlider()
{
this.InitializeComponent();
this.LayoutUpdated += new EventHandler(RangeSlider_LayoutUpdated);
}
void RangeSlider_LayoutUpdated(object sender, EventArgs e)
{
SetProgressBorder();
}
private void SetProgressBorder()
{
double lowerPoint = (this.ActualWidth * (LowerValue - Minimum)) / (Maximum - Minimum);
double upperPoint = (this.ActualWidth * (UpperValue - Minimum)) / (Maximum - Minimum);
upperPoint = this.ActualWidth - upperPoint;
progressBorder.Margin = new Thickness(lowerPoint, 0, upperPoint, 0);
}
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 LowerValue
{
get { return (double)GetValue(LowerValueProperty); }
set { SetValue(LowerValueProperty, value); }
}
public double UpperValue
{
get { return (double)GetValue(UpperValueProperty); }
set { SetValue(UpperValueProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d, new PropertyChangedCallback(PropertyChanged)));
public static readonly DependencyProperty LowerValueProperty =
DependencyProperty.Register("LowerValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(10d, new PropertyChangedCallback(PropertyChanged)));
public static readonly DependencyProperty UpperValueProperty =
DependencyProperty.Register("UpperValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(90d, new PropertyChangedCallback(PropertyChanged)));
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(100d, new PropertyChangedCallback(PropertyChanged)));
private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RangeSlider slider = (RangeSlider)d;
if (e.Property == RangeSlider.LowerValueProperty)
{
slider.UpperSlider.Value = Math.Max(slider.UpperSlider.Value, slider.LowerSlider.Value);
}
else if (e.Property == RangeSlider.UpperValueProperty)
{
slider.LowerSlider.Value = Math.Min(slider.UpperSlider.Value, slider.LowerSlider.Value);
}
slider.SetProgressBorder();
}
}
Label x:Name="PART_ValueOfSlider"
包含较小的值时,它可以正常工作。
当Label x:Name="PART_ValueOfSlider"
具有较大值时,ProgressBorder显示不会像我预期的那样显示
如何设置ProgressBorder工作正常?谢谢你的帮助!!!
答案 0 :(得分:1)
我正在使用一个滑块Just Like You但它的工作对我来说很好Slider的Xaml代码
<ControlTemplate x:Key="TimeRangeSliderTemplate" TargetType="{x:Type Slider}">
<StackPanel>
<Border SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="PART_SelectionRange"/>
<Track x:Name="PART_Track" Grid.Row="1">
<Track.Thumb>
<Thumb x:Name="Thumb">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Red"
Stroke="Black"
StrokeThickness="1"
Width="10"
Height="18"
SnapsToDevicePixels="True"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
</StackPanel>
</ControlTemplate>
<Style TargetType="{x:Type sliders:TimeRangeSlider}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type sliders:TimeRangeSlider}">
<Grid VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=Part_LowerSlider,Path=Value}" Foreground="Red" VerticalAlignment="Top" Margin="{Binding ElementName=Part_SelectedRect,Path=Margin}"/>
<TextBlock x:Name="PART_RIGHTTHUMPVALUE" Text="{Binding ElementName=Part_UpperSlider,Path=Value}" Foreground="Red" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</StackPanel>
<Grid Grid.Row="1">
<Border BorderThickness="0,1,0,0" BorderBrush="Black" VerticalAlignment="Center" Height="1" Margin="5,0,5,0"/>
<Rectangle x:Name="Part_SelectedRect" Fill="Green" Height="10" HorizontalAlignment="Left"/>
<Slider x:Name="Part_LowerSlider"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"
Value="{TemplateBinding LowerValue}"
Template="{StaticResource TimeRangeSliderTemplate}"
Margin="0,0,0,0"/>
<Slider x:Name="Part_UpperSlider"
Minimum="{TemplateBinding Minimum}"
Maximum="{TemplateBinding Maximum}"
Value="{TemplateBinding UpperValue}"
Template="{StaticResource TimeRangeSliderTemplate}"
Margin="0,0,0,0"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这是Xaml的Cs文件
public class TimeRangeSlider : Control
{
private const string PartName_LowerSlider = "Part_LowerSlider";
private const string PartName_UpperSlider = "Part_UpperSlider";
private const string PartName_SelectedRegion = "Part_SelectedRect";
private const string PART_RIGHTTHUMPVALUE = "PART_RIGHTTHUMPVALUE";
private Slider lowerSlider;
private Slider upperSlider;
Rectangle selectedRect;
TextBlock rightText;
public TimeRangeSlider()
{
this.DefaultStyleKey = typeof(TimeRangeSlider);
this.Loaded += TimeRangeSlider_Loaded;
}
void TimeRangeSlider_Loaded(object sender, RoutedEventArgs e)
{
lowerSlider.ValueChanged += LowerSlider_ValueChanged;
upperSlider.ValueChanged += UpperSlider_ValueChanged;
lowerSlider.Minimum = Minimum;
lowerSlider.Maximum = Maximum;
lowerSlider.Value = LowerValue;
upperSlider.Minimum = Minimum;
upperSlider.Maximum = Maximum;
upperSlider.Value = UpperValue;
SetView();
}
public override void OnApplyTemplate()
{
lowerSlider = this.GetTemplateChild(PartName_LowerSlider) as Slider;
upperSlider = this.GetTemplateChild(PartName_UpperSlider) as Slider;
selectedRect = this.GetTemplateChild(PartName_SelectedRegion) as Rectangle;
rightText = this.GetTemplateChild(PART_RIGHTTHUMPVALUE) as TextBlock;
base.OnApplyTemplate();
}
private void LowerSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
upperSlider.Value = Math.Max(upperSlider.Value, lowerSlider.Value);
SetView();
}
private void UpperSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lowerSlider.Value = Math.Min(upperSlider.Value, lowerSlider.Value);
SetView();
}
private void SetView()
{
LowerValue = lowerSlider.Value;
UpperValue = upperSlider.Value;
var unit = lowerSlider.ActualWidth / Maximum;
var leftMargin = LowerValue * unit;
if (UpperValue > LowerValue)
{
var width = (UpperValue - LowerValue) * unit;
selectedRect.Width = width;
}
selectedRect.Margin = new Thickness(leftMargin, 0, 0, 0);
rightText.Margin = new Thickness(selectedRect.Width-20, 0, 0, 0);
}
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(TimeRangeSlider), new UIPropertyMetadata(0d));
public double LowerValue
{
get { return (double)GetValue(LowerValueProperty); }
set { SetValue(LowerValueProperty, value); }
}
public static readonly DependencyProperty LowerValueProperty =
DependencyProperty.Register("LowerValue", typeof(double), typeof(TimeRangeSlider), new UIPropertyMetadata(0d));
public double UpperValue
{
get { return (double)GetValue(UpperValueProperty); }
set { SetValue(UpperValueProperty, value); }
}
public static readonly DependencyProperty UpperValueProperty =
DependencyProperty.Register("UpperValue", typeof(double), typeof(TimeRangeSlider), new UIPropertyMetadata(0d));
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(TimeRangeSlider), new UIPropertyMetadata(1d));
}
以及控件的使用
<SliderControl:TimeRangeSlider x:Name="slider"
Margin="10"
LowerValue="30"
UpperValue="70"
Minimum="0"
Maximum="100"
/>
答案 1 :(得分:0)
画布中的元素不会影响度量。所以,使用代码:
<Canvas>
<Label x:Name="PART_ValueOfSlider" Content="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"
Margin="0 0 0 0"
HorizontalAlignment="Center"
Foreground="Red">
<Label.RenderTransform>
<ScaleTransform ScaleY="-1" />
</Label.RenderTransform>
<Label.LayoutTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" />
</TransformGroup>
</Label.LayoutTransform>
</Label>
</Canvas>