首页 > 解决方案 > 在 Xaml 中,如何将滑块的 Thumb 绑定到多个 ControlTemplate 之一?

问题描述

我正在尝试在 WPF 中创建一个可编辑的滑块,我需要在其中将 ControlTemplate 与不起作用的 Slider thumb 的模板绑定。

我有 2 个 ControlTemplate 和一个滑块。滑块的拇指应根据控件模板的选择显示。

<ControlTemplate x:Uid="ControlTemplate_3" x:Key="StaticThumbTemplate" TargetType="{x:Type Thumb}">
        <Border x:Uid="Border_3" Margin="1" BorderBrush="Gray" BorderThickness="1" Background="#EEEEEE" MinWidth="30" MaxWidth="50">
                <TextBlock x:Uid="TextBlock_3" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="2,0,2,0"

                Text="{Binding Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>

        </Border>
</ControlTemplate>

 <ControlTemplate x:Uid="ControlTemplate_4" x:Key="EditThumbTemplate" TargetType="{x:Type Thumb}">
         <TextBox x:Uid="PART_Edit" Padding="2,0,2,0" x:Name="PART_Edit" MinWidth="30" VerticalAlignment="Center" LostFocus="PART_Edit_LostFocus"

                 Text="{Binding Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}, Mode=TwoWay}" />

 </ControlTemplate>

    <Style x:Uid="Style_3" x:Key="ThumbStyle" TargetType="{x:Type Thumb}">
    <Setter x:Uid="Setter_3" Property="Template" Value="{StaticResource StaticThumbTemplate}"/>
    <Style.Triggers>
    <DataTrigger Binding="{Binding IsTyping, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}}" Value="True">
    <Setter x:Uid="Setter_4" Property="Template" Value="{StaticResource EditThumbTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>

如果属性IsTyping从 true/false 更改,则应显示相应的 ControlTemplate。目前只有Static Thumb TemplateControlTemplate 一直被列出。

[更新1] Slider.xaml的完整代码:

<Slider x:Class="SliderTest.Slider"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:SliderTest"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Slider.Resources>
    <!-- TODO: Focus highlight! -->

    <Style x:Uid="Style_1" x:Key="SliderLeftStyle" TargetType="{x:Type RepeatButton}">
        <Setter x:Uid="Setter_1" Property="Template">
            <Setter.Value>
                <ControlTemplate x:Uid="ControlTemplate_1" TargetType="{x:Type RepeatButton}">
                    <Border x:Uid="Border_1" Background="Transparent">
                        <TextBlock x:Uid="TextBlock_1" Margin="2" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding MinStr, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Uid="Style_2" x:Key="SliderRightStyle" TargetType="{x:Type RepeatButton}">
        <Setter x:Uid="Setter_2" Property="Template">
            <Setter.Value>
                <ControlTemplate x:Uid="ControlTemplate_2" TargetType="{x:Type RepeatButton}">
                    <Border x:Uid="Border_2" Background="Transparent">
                        <TextBlock x:Uid="TextBlock_2" Margin="2" HorizontalAlignment="Right" VerticalAlignment="Center" Text="{Binding MaxStr, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <ControlTemplate x:Uid="ControlTemplate_3" x:Key="StaticThumbTemplate" TargetType="{x:Type Thumb}">
        <Border x:Uid="Border_3" Margin="1" BorderBrush="Gray" BorderThickness="1" Background="#EEEEEE" MinWidth="30" MaxWidth="50">
            <TextBlock x:Uid="TextBlock_3" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="2,0,2,0"
                       Text="{Binding Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
                       />
        </Border>
    </ControlTemplate>

    <ControlTemplate x:Uid="ControlTemplate_4" x:Key="EditThumbTemplate" TargetType="{x:Type Thumb}">
        <TextBox x:Uid="PART_Edit" Padding="2,0,2,0" x:Name="PART_Edit" MinWidth="30" VerticalAlignment="Center" LostFocus="PART_Edit_LostFocus" 
                 Text="{Binding Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}, Mode=TwoWay}" />
    </ControlTemplate>

    <Style x:Uid="Style_3" x:Key="ThumbStyle" TargetType="{x:Type Thumb}">
        <Setter x:Uid="Setter_3" Property="Template" Value="{StaticResource StaticThumbTemplate}"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsTyping, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="True">
                <Setter x:Uid="Setter_4" Property="Template" Value="{StaticResource EditThumbTemplate}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Slider.Resources>

<Slider.Template>
    <ControlTemplate x:Uid="ControlTemplate_5">
        <Grid x:Uid="Grid_1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Uid="ColumnDefinition_1" Width="*"/>
                <ColumnDefinition x:Uid="ColumnDefinition_2" Width="Auto"/>
                <ColumnDefinition x:Uid="ColumnDefinition_3" Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Border x:Uid="Border_4" Grid.Column="0" BorderBrush="Gray" BorderThickness="1">
                <DockPanel x:Uid="PART_Outer" x:Name="PART_Outer" >
                    <Border x:Uid="Border_5" DockPanel.Dock="Left" Background="LightGray" Width="{Binding PadLeft, RelativeSource={RelativeSource Mode=TemplatedParent}}" Focusable="True"></Border>
                    <Border x:Uid="Border_6" DockPanel.Dock="Right" Background="LightGray" Width="{Binding PadRight, RelativeSource={RelativeSource Mode=TemplatedParent}}" Focusable="False"></Border>
                    <Track x:Uid="PART_Track" x:Name="PART_Track">
                        <Track.DecreaseRepeatButton>
                            <RepeatButton x:Uid="RepeatButton_1" Style="{StaticResource SliderLeftStyle}" Command="Slider.DecreaseLarge"/>
                        </Track.DecreaseRepeatButton>
                        <Track.Thumb>
                            <Thumb x:Uid="PART_Thumb" x:Name="PART_Thumb" Style="{StaticResource ThumbStyle}" MouseDoubleClick="PART_Thumb_OnMouseDoubleClick"/>
                        </Track.Thumb>
                        <Track.IncreaseRepeatButton>
                            <RepeatButton x:Uid="RepeatButton_2" Style="{StaticResource SliderRightStyle}" Command="Slider.IncreaseLarge" />
                        </Track.IncreaseRepeatButton>
                    </Track>
                </DockPanel>
            </Border>
            <RepeatButton x:Uid="RepeatButton_3" Grid.Column="1" Padding="4,0,4,0" Command="Slider.DecreaseSmall">&lt;</RepeatButton>
            <RepeatButton x:Uid="RepeatButton_4" Grid.Column="2" Padding="4,0,4,0" Command="Slider.IncreaseSmall">&gt;</RepeatButton>

        </Grid>

    </ControlTemplate>
</Slider.Template>

Slider.xaml.cs:

public partial class Slider 
{
    private bool _isTyping;
    public Slider()
    {
        InitializeComponent();
    }

    public bool IsTyping
    {
        get
        {
            return _isTyping;
        }
        set
        {
            _isTyping = value;
        }
    }

    private double _valStr;

    public double ValueStr
    {
        get { return _valStr; }
        set { _valStr = value; }
    }


    private void PART_Thumb_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        IsTyping = true;
    }

    private void PART_Edit_LostFocus(object sender, RoutedEventArgs e)
    {
        IsTyping = false;
    }
}

标签: wpfxamlslider

解决方案


属性在哪里IsTyping定义?如果是控件的属性DataContextSlider则应添加“DataContext”。到绑定路径:

<DataTrigger Binding="{Binding DataContext.IsTyping, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Slider}}" Value="True">

如果它是在父窗口的视图模型中定义的,您还应该更改AncestorType

<DataTrigger Binding="{Binding DataContext.IsTyping, 
              RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="True">

还要确保它IsTyping是一个依赖属性,或者定义它的类实现了接口,并且在属性被设置为新值时INotifyPropertyChanged引发事件。PropertyChanged


推荐阅读