我为自己的应用创建了自定义滑块和缩略图模板。除了PART_SelectionRange Rectangle之外,它正如预期的那样工作,它略微落后于拇指,到达最大值的时间远远落后于它。
我不知道如何解决这个问题,因为看起来问题出在任何类控制PART_SelectionRange Rectangle大小的行为中。
<ControlTemplate x:Key="SliderThumbHorizontalDefault" TargetType="{x:Type Thumb}">
<Grid>
<!-- SliderThumb -->
<Path x:Name="grip" Data="M-0.4,6.4 C1.2,1 9,1 10.5,6.5 12,11.787571 5.0267407,18.175417 5.0267407,18.175417 5.0267407,18.175417 -2,11.8 -0.4,6.4 z"
Fill="White" Stretch="Fill" SnapsToDevicePixels="True"
Stroke="Black" StrokeThickness="1" UseLayoutRounding="True" />
<ContentPresenter Margin="0 4 0 0" Content="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}" TextBlock.Foreground="Black" TextBlock.FontSize="20" TextBlock.TextAlignment="Center" />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="SliderHorizontal" TargetType="{x:Type Slider}">
<ControlTemplate.Resources>
<vc:TickConverter x:Key="TickConverter" />
</ControlTemplate.Resources>
<Grid Height="{StaticResource SliderHeight}">
<Border x:Name="TrackBackground" BorderBrush="{StaticResource SliderThumb.Track.Border}" BorderThickness="0"
Background="White"
CornerRadius="{Binding ActualHeight, Converter={StaticResource HalvingConverter}, ElementName=TrackBackground}">
<!-- This rectangle is what lags behind! -->
<Rectangle x:Name="PART_SelectionRange" Fill="SlateBlue"
HorizontalAlignment="Left" RadiusY="3" RadiusX="3" />
</Border>
<Track x:Name="PART_Track" >
<Track.Thumb>
<Thumb x:Name="Thumb" Focusable="False" Width="35" Height="47" OverridesDefaultStyle="True"
Template="{StaticResource SliderThumbHorizontalDefault}" Margin="-14.65,-55,-16,12"/>
</Track.Thumb>
</Track>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelectionRangeEnabled" Value="true">
<Setter Property="Visibility" TargetName="PART_SelectionRange" Value="Visible" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Foreground" TargetName="Thumb" Value="Blue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type Slider}">
<Setter Property="MinHeight" Value="{StaticResource SliderHeight}" />
<Setter Property="MaxHeight" Value="{StaticResource SliderHeight}" />
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
<Setter Property="IsSelectionRangeEnabled" Value="True" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource SliderThumb.Static.Foreground}" />
<Setter Property="SelectionStart" Value="{Binding Minimum, RelativeSource={RelativeSource Self}}" />
<Setter Property="SelectionEnd" Value="{Binding Value, RelativeSource={RelativeSource Self}}" />
<Setter Property="Template" Value="{StaticResource SliderHorizontal}" />
</Style>
此时我不知道应该尝试修改什么。我相信我已经尝试过改变xaml中有意义的所有属性,所以我认为问题出在Slider类中,但无法理解在哪里。
答案 0 :(得分:1)
很遗憾,您只能使用自定义Slider
和Style
来更改ControlTemplate
的此行为。
原因是Slider
控件根据Thumb
的宽度调整选择范围的宽度。当您将滑块位置移向Maximum
值时,这会导致选择范围栏“挂起”。如果您希望选择范围完全遵循Value
,则需要将Thumb
宽度设置为0.但是,显然,您将无法移动拇指将不再有热门测试。
这是相应选择范围大小和位置调整的current implementation:
if (DoubleUtil.AreClose(range, 0d) || (DoubleUtil.AreClose(trackSize.Width, thumbSize.Width)))
{
valueToSize = 0d;
}
else
{
valueToSize = Math.Max(0.0, (trackSize.Width - thumbSize.Width) / range);
}
rangeElement.Width = ((SelectionEnd - SelectionStart) * valueToSize);
if (IsDirectionReversed)
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(Maximum - SelectionEnd, 0) * valueToSize);
}
else
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(SelectionStart - Minimum, 0) * valueToSize);
}
您现在有两个选择:
Thumb
宽度"PART_SelectionRange"
中的选择矩形中移除ControlTemplate
名称,并将Binding
与IValueConverter
s(或Behavior
s或附加属性一起使用)手动控制外观答案 1 :(得分:0)
根据@dymanoid的回答,我手动实现了行为(在创建新滑块失败后)。
我删除了PART_SelectionRange控件(必须使其透明或不会编译),将其替换为另一个矩形。
<Border x:Name="TrackBackground" BorderBrush="{StaticResource SliderThumb.Track.Border}" BorderThickness="0"
Background="{StaticResource SliderThumb.Track.Background}"
CornerRadius="{Binding ActualHeight, Converter={StaticResource HalvingConverter}, ElementName=TrackBackground}">
<Rectangle x:Name="SelectionRange" Fill="{StaticResource SliderThumb.Track.BackgroundSelected}"
HorizontalAlignment="Left" RadiusY="3" RadiusX="3">
<Rectangle.Width>
<MultiBinding Converter="{StaticResource SliderToSelectionWidthConverter}">
<Binding Path="Value" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="Maximum" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="Minimum" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}"/>
</MultiBinding>
</Rectangle.Width>
</Rectangle>
</Border>
相关的是它的宽度绑定到Slider的Value,Minimum,Maximum和ActualWidth属性。使用此转换器:
class SliderToSelectionWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var Value = (double) values[0];
var Minimum = (double) values[1];
var Maximum = (double) values[2];
var ActualWidth = (double) values[3];
return (1 - (Value - Minimum) / (Maximum - Minimum)) * ActualWidth;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
这些值可用于计算SelectionRange矩形的实际宽度。为什么在默认的Slider中没有这样做是超出我的。