自定义带三角形拇指的WPF滑块

5

我的目标是制作一个像这样的滑块:

期望的滑块

问题在于,当我将滑块移动到最大值时,三角形的顶点不会达到最高点,它停留在这个位置:

最大值

我认为问题的原因是 Thumb 的位置被限制在其大小范围内,因此它不能超出滑块的限制……但在我的情况下,这正是我想要实现的!我尝试改变 Thumb 的高度,但这可能对 Top 有所帮助,但在滑块的 Bottom 中就会出现问题。

我的代码缺少什么?

到目前为止,我的代码是:

滑块:

<Slider Grid.Row="1"
        Grid.Column="1"
        Maximum="1000" 
        Orientation="Vertical" 
        HorizontalAlignment="Center"
        Margin="20,0,20,20"
        Height="150" 
        Style="{DynamicResource LampadaSliderStyle}" />

重复按钮样式:
<Style x:Key="SliderRepeatButtonStyle" TargetType="{x:Type RepeatButton}">
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="IsTabStop" Value="false"/>
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Rectangle Fill="Transparent"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

拇指样式:
<Style x:Key="LampadaThumbStyle" TargetType="{x:Type Thumb}">
    <Setter Property="Focusable" Value="false"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="Height" Value="20"/>
    <Setter Property="Width" Value="20"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Canvas SnapsToDevicePixels="true">                        
                    <Path Data="M8.1965079,-17.994989 L28.196667,-28.213333 28.196333,-8.213772 z" 
                          Fill="Black" 
                          Height="20" 
                          Canvas.Left="23.197" 
                          Stretch="Fill" 
                          Canvas.Top="9.768" 
                          Width="20"/>
                </Canvas>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

滑块样式:
<Style x:Key="LampadaSliderStyle" TargetType="{x:Type Slider}">
    <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Slider}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MinWidth="{TemplateBinding MinWidth}" Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <UniformGrid x:Name="TrackBackground" 
                                     Rows="6" 
                                     Columns="0">
                            <Rectangle Fill="Red" />
                            <Rectangle Fill="Orange" />
                            <Rectangle Fill="Yellow" />
                            <Rectangle Fill="LightGreen" />
                            <Rectangle Fill="Green" />
                            <Rectangle Fill="DarkGreen" />
                        </UniformGrid>
                        <Canvas Margin="-1,-6">
                            <Rectangle x:Name="PART_SelectionRange" 
                                               Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" 
                                               Stroke="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" 
                                               StrokeThickness="1.0" 
                                               Visibility="Hidden" 
                                               Width="4.0"/>
                        </Canvas>
                        <Track x:Name="PART_Track">
                            <Track.DecreaseRepeatButton>
                                <RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource SliderRepeatButtonStyle}"/>
                            </Track.DecreaseRepeatButton>
                            <Track.IncreaseRepeatButton>
                                <RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource SliderRepeatButtonStyle}"/>
                            </Track.IncreaseRepeatButton>
                            <Track.Thumb>
                                <Thumb x:Name="Thumb" Style="{DynamicResource LampadaThumbStyle}"/>
                            </Track.Thumb>
                        </Track>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我通过编辑默认模板来创建它们。

1个回答

4

您可以做的最简单的调整是设置一个顶部边距为10(即Path高度的一半),以便将轨道背景放置得足够低,使三角形的尖端与之匹配:

<UniformGrid x:Name="TrackBackground" Rows="6" Columns="0" 
             Margin="0,10,0,0">
     <!-- ... -->
</UniformGrid>

你在多个位置都使用了UniformGrid,请相应地进行修改。

嗯,这个可以解决问题......但是我总是会在控件中留有一些余地,我宁愿不依赖于这个... - Michel Feinstein
@mFeinstein 这不是你控件的边距,而是内部控件的边距。不确定为什么您拒绝使用如此漂亮的解决方案。如果不使用类似这样的间距,我确信其他方法非常复杂(可能涉及代码背后)。 - King King
你的控件边界仍然包含三角形的顶部边缘,我的意思是在顶点经过的上水平线和控件的上边框之间没有任何间距。 - King King
我不得不确保边距与路径高度相等,但我不确定为什么...我猜这可能与滑块计算拇指位置有关... - Michel Feinstein
1
我简化了代码,现在只有一个UniformGrid。 - Michel Feinstein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接