椭圆滑块拇指上的文本块 - 避免在文本更改时调整椭圆后面的网格大小 C# WPF

Textblock over the elipse slider thumb - avoid resize of grid behind elipse when text is changing C# WPF

我想在椭圆滑块拇指顶部实现带有滑块实际值的文本块。当文本块的宽度与 elipse 相同时,一切正常,但我需要增加文本块的宽度。

在 textloblock 的宽度改变后,椭圆的网格宽度也改变了,滑块看起来不再合适了。

  1. 文本块宽度 = 椭圆宽度的滑块图片 textblock width = elipse width

  2. 文本块宽度大于椭圆宽度 texblock width higher

你知道如何避免图 2 中的情况吗?

滑块拇指样式:

            <Thumb x:Name="SliderThumb">
               <Thumb.Style>
                 <Style  TargetType="Thumb">
                   <Setter Property="SnapsToDevicePixels" Value="true" />
                   <Setter Property="OverridesDefaultStyle" Value="true" />
                   <Setter Property="Template">
                     <Setter.Value>
                       <ControlTemplate  TargetType="Thumb">
                         <Grid  Background="Transparent">
                           <Ellipse VerticalAlignment="Center"  HorizontalAlignment="Center" Fill="Blue" Height="30" Width="30"/>
                           <TextBlock  Width="60" TextAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,80"
                            HorizontalAlignment="Center" Background="Transparent" Foreground="Black" FontSize="24" 
                            Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                         </Grid>
                     </ControlTemplate>
                   </Setter.Value>
                 </Setter>
              </Style>
            </Thumb.Style>
          </Thumb>

编辑: 根据文本居中问题的完整代码。

主窗口:

 <Grid>
    <ContentControl   Height="70" Width="400">
       <Slider x:Name="slider2"  IsMoveToPointEnabled="True" Tag="mm" Maximum="210"  Width="300" VerticalAlignment="Bottom" Grid.Row="0" Style="{StaticResource Horizontal_Slider}"/>
    </ContentControl> 
</Grid>

滑块样式:

            <Style x:Key="SliderRepeatButton" TargetType="RepeatButton">
                <Setter Property="SnapsToDevicePixels" Value="true" />
                <Setter Property="OverridesDefaultStyle" Value="true" />
                <Setter Property="IsTabStop" Value="false" />
                <Setter Property="Focusable" Value="false" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="RepeatButton">
                            <Border Height="10" Background="Red"/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

            <Style x:Key="SliderRepeatButton1" TargetType="RepeatButton">
                <Setter Property="SnapsToDevicePixels" Value="true" />
                <Setter Property="OverridesDefaultStyle" Value="true" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="RepeatButton">
                            <Border Height="10" Background="Blue" SnapsToDevicePixels="True" />
                        </ControlTemplate>
                    </Setter.Value>
               </Setter>
           </Style>
           
           
           <Style x:Key="SliderThumb" TargetType="Thumb">
                <Setter Property="SnapsToDevicePixels" Value="true" />
                <Setter Property="OverridesDefaultStyle" Value="true" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Thumb">
                            <Grid MaxWidth="{Binding ElementName=ellipseThumb, Path=ActualWidth}"                                                      Background="Transparent">
                                <Ellipse x:Name="ellipseThumb" Fill="Blue" Height="30"Width="30"/> 
                                 <Canvas Margin="0,0,0,100" ClipToBounds="False"
                                    Height="{Binding ElementName=valueTextBlock, Path=ActualHeight}"
                                    Width="{Binding ElementName=valueTextBlock, Path=ActualWidth}">
                                    <TextBlock                   
                                       Background="Transparent"
                                       Foreground="{TemplateBinding Background}"
                                       FontSize="24"> 
                                       <Run Text="{Binding Value,StringFormat={}{0:F2}, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                                       <Run Text="{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                                    </TextBlock>
                                </Canvas>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
            
            
            <ControlTemplate x:Key="CustomSlider"  TargetType="Slider">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Track Grid.Row="1" x:Name="PART_Track"   >
                        <Track.DecreaseRepeatButton>
                            <RepeatButton x:Name="DecreaseSlider" Style="{StaticResource SliderRepeatButton1}"  Command="Slider.DecreaseLarge" />
                        </Track.DecreaseRepeatButton>
                        <Track.Thumb>
                            <Thumb x:Name="SliderThumb"  Style="{StaticResource SliderThumb}"  />
                        </Track.Thumb>
                        <Track.IncreaseRepeatButton>
                            <RepeatButton x:Name="IncreaseSlider" Style="{StaticResource SliderRepeatButton}" Command="Slider.IncreaseLarge" />
                        </Track.IncreaseRepeatButton>
                    </Track>
                </Grid>              
            </ControlTemplate>



           <Style x:Key="Horizontal_Slider" TargetType="Slider">
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="SnapsToDevicePixels" Value="true" />
                <Setter Property="OverridesDefaultStyle" Value="true" />
                <Style.Triggers>
                    <Trigger Property="Orientation" Value="Horizontal">
                        <Setter Property="MinHeight" Value="21" />
                        <Setter Property="MinWidth" Value="104" />
                        <Setter Property="Template" Value="{StaticResource CustomSlider}" />
                    </Trigger>
                </Style.Triggers>
            </Style>

您必须将 TextBlock 包裹在 Canvas 中以避免剪裁,并且您还需要不设置 TextBLock 的宽度以使其获得所需的大小。

这是适用于您的案例的工作代码:

<Thumb x:Name="SliderThumb">
    <Thumb.Style>
        <Style  TargetType="Thumb">
            <Setter Property="SnapsToDevicePixels" Value="true" />
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Thumb">
                        <Grid Background="Transparent" MaxWidth="{Binding ElementName=ellipse, Path=ActualWidth}">
                            <Ellipse x:Name="ellipse" VerticalAlignment="Center" HorizontalAlignment="Center" Fill="Blue" Height="30" Width="30"/>
                            <Canvas Margin="0,0,0,80"
                                    Height="{Binding ElementName=valueTextBlock, Path=ActualHeight}"
                                    Width="{Binding ElementName=valueTextBlock, Path=ActualWidth}"
                                    HorizontalAlignment="Center">
                                <TextBlock x:Name="valueTextBlock"
                                           Background="Transparent"
                                           Foreground="Black"
                                           FontSize="24"
                                           Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                            </Canvas>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Thumb.Style>
</Thumb>

更新

这是 Thumb 的更好样式,对齐方式更好

<Style x:Key="SliderThumb" TargetType="Thumb">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Thumb">
                <Grid MaxWidth="{Binding ElementName=ellipseThumb, Path=ActualWidth}"
                      MaxHeight="{Binding ElementName=ellipseThumb, Path=ActualHeight}"
                      Background="Transparent">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Ellipse x:Name="ellipseThumb" Fill="Blue" Height="30" Width="30" Grid.Row="1"/>
                    <Canvas Grid.Row="0"
                            Height="{Binding ElementName=valueBorder, Path=ActualHeight}"
                            Width="{Binding ElementName=valueBorder, Path=ActualWidth}"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Bottom">
                        <Border x:Name="valueBorder">
                            <TextBlock Margin="0,0,0,5"
                                       Background="Transparent"
                                       Foreground="Black"
                                       FontSize="24">
                                <Run Text="{Binding Value,StringFormat={}{0:F2}, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                                <Run Text="{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type Slider}}}"/>
                            </TextBlock>
                        </Border>
                    </Canvas>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我已将 TextBlock 包裹在 Border 中以使其有余量。

注意:为了测试目的,我将 TextBlockForeground 颜色设置为黑色。