在 MVVM 中单击按钮时清除 TextBox 的文本

发布于 2025-01-11 14:00:46 字数 1979 浏览 0 评论 0原文

我正在开发一个搜索框解决方案,其中没有绑定文本,因为我使用 Text 属性作为搜索命令的参数。 那部分工作得很好。

现在我想使用 TextBox 末尾设置的“清除按钮”清除 TextBox 中的文本。

我尝试使用 EventTrigger,但 StoryBoard 阻止 Command 并且不会将文本设置为零。

下面是我的代码。 有什么想法吗?

<!--Search Box-->
<Grid Grid.Column="0">
    <TextBox x:Name="FilterText">
        <TextBox.InputBindings>
            <KeyBinding  Key="Enter" Command="{Binding FilterDataCommand}" CommandParameter="{Binding ElementName=FilterText, Path=Text}"/>
        </TextBox.InputBindings>
    </TextBox>
    <Button HorizontalAlignment="Right" Width="20" Height="20" Margin="5,0" Style="{StaticResource ButtonTransparentStyle}" Command="{Binding ClearSearchCommand}">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <StringAnimationUsingKeyFrames Storyboard.TargetName="FilterText" Storyboard.TargetProperty="Text">
                            <DiscreteStringKeyFrame KeyTime="0:0:1" Value=""/>
                        </StringAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
        <Image Source="/VisionRanger;component/Images/Icons/icon.clear.dark.png" Stretch="UniformToFill" Margin="4,3,2,4" Opacity="0.5"/>
    </Button>
</Grid>
<!--Search Button-->
<Button Grid.Column="1"  Style="{StaticResource ButtonTransparentStyle}" Margin="5,0,0,0" Width="25" HorizontalAlignment="Left"
    Command="{Binding FilterDataCommand}" CommandParameter="{Binding ElementName=FilterText, Path=Text}">
    <Image Source="/VisionRanger;component/Images/Icons/icon.search.dark.png" Stretch="UniformToFill"/>
</Button>

I'm working on a search box solution where there is no binded text as I'm using the Text property as parameter for the search command.
And that part works just fine.

Now I would like to clear the text in the TextBox using a "clear button" set at the end of the TextBox.

I tried with EventTrigger, but the StoryBoard block the Command and does not set the text to nil.

Below is my code.
Any idea?

<!--Search Box-->
<Grid Grid.Column="0">
    <TextBox x:Name="FilterText">
        <TextBox.InputBindings>
            <KeyBinding  Key="Enter" Command="{Binding FilterDataCommand}" CommandParameter="{Binding ElementName=FilterText, Path=Text}"/>
        </TextBox.InputBindings>
    </TextBox>
    <Button HorizontalAlignment="Right" Width="20" Height="20" Margin="5,0" Style="{StaticResource ButtonTransparentStyle}" Command="{Binding ClearSearchCommand}">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <StringAnimationUsingKeyFrames Storyboard.TargetName="FilterText" Storyboard.TargetProperty="Text">
                            <DiscreteStringKeyFrame KeyTime="0:0:1" Value=""/>
                        </StringAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
        <Image Source="/VisionRanger;component/Images/Icons/icon.clear.dark.png" Stretch="UniformToFill" Margin="4,3,2,4" Opacity="0.5"/>
    </Button>
</Grid>
<!--Search Button-->
<Button Grid.Column="1"  Style="{StaticResource ButtonTransparentStyle}" Margin="5,0,0,0" Width="25" HorizontalAlignment="Left"
    Command="{Binding FilterDataCommand}" CommandParameter="{Binding ElementName=FilterText, Path=Text}">
    <Image Source="/VisionRanger;component/Images/Icons/icon.search.dark.png" Stretch="UniformToFill"/>
</Button>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

缱倦旧时光 2025-01-18 14:00:46

Text 属性不可动画化,请参阅文档中的备注。在参考源中, FrameworkPropertyMetadata 初始化为 isAnimationProhibited 设置为 true

解决方案是将 MyFilterTextProperty 属性绑定到 TwoWay 模式下 TextBoxText 属性(即默认值)。

<TextBox Text="{Binding MyFilterTextProperty}"/>

然后在命令 ClearSearchCommand 中,您可以清除 MyFilterTextProperty

public void ExecuteClearSearchCommand(/*...parameter.*/)
{
   MyFilterTextProperty = string.Empty;
   
   // ...other code.
}

另一种方法是使用自定义 TriggerAction 清除 TextBox。安装Microsoft.Xaml.Behaviors.Wpf NuGet 包。创建一个像这样的自定义触发操作。它公开了 TextBox 可以绑定到的依赖属性 Target。如果发生事件,则会将其清除。

public class ClearTextTriggerAction : TriggerAction<Button>
{
   public static TextBox GetTarget(DependencyObject obj)
   {
      return (TextBox)obj.GetValue(TargetProperty);
   }

   public static void SetTarget(DependencyObject obj, int value)
   {
      obj.SetValue(TargetProperty, value);
   }

   public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
      "Target", typeof(TextBox), typeof(ClearTextTriggerAction), new PropertyMetadata(null));

   protected override void Invoke(object parameter)
   {
      GetTarget(this)?.Clear();
   }
}

在 XAML 中,您只需附加行为并绑定 FilterText

<Button HorizontalAlignment="Right" Width="20" Height="20" Margin="5,0" Style="{StaticResource ButtonTransparentStyle}" Command="{Binding ClearSearchCommand}">
    <b:Interaction.Triggers>
       <b:EventTrigger EventName="Click">
          <local:ClearTextTriggerAction Target="{Binding ElementName=FilterText}"/>
       </b:EventTrigger>
    </b:Interaction.Triggers>
    <Image Source="/VisionRanger;component/Images/Icons/icon.clear.dark.png" Stretch="UniformToFill" Margin="4,3,2,4" Opacity="0.5"/>
</Button>

必须包含 XAML bahviors 的 b XML 命名空间。

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"

The Text property is not animatable, see Remarks in the documentation. In the reference source, the FrameworkPropertyMetadata is initialized with isAnimationProhibited set to true.

A solution would be to bind a MyFilterTextProperty property to the Text property of the TextBox in TwoWay mode (which is the default).

<TextBox Text="{Binding MyFilterTextProperty}"/>

Then in your command ClearSearchCommand you could clear MyFilterTextProperty.

public void ExecuteClearSearchCommand(/*...parameter.*/)
{
   MyFilterTextProperty = string.Empty;
   
   // ...other code.
}

An alternative is to clear the TextBox using a custom TriggerAction. Install the Microsoft.Xaml.Behaviors.Wpf NuGet package. Create a custom trigger action like this. It exposes a dependency property Target that the TextBox can be bound to. If an event occurs, it clears it.

public class ClearTextTriggerAction : TriggerAction<Button>
{
   public static TextBox GetTarget(DependencyObject obj)
   {
      return (TextBox)obj.GetValue(TargetProperty);
   }

   public static void SetTarget(DependencyObject obj, int value)
   {
      obj.SetValue(TargetProperty, value);
   }

   public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached(
      "Target", typeof(TextBox), typeof(ClearTextTriggerAction), new PropertyMetadata(null));

   protected override void Invoke(object parameter)
   {
      GetTarget(this)?.Clear();
   }
}

In XAML you simply attach the behavior and bind FilterText

<Button HorizontalAlignment="Right" Width="20" Height="20" Margin="5,0" Style="{StaticResource ButtonTransparentStyle}" Command="{Binding ClearSearchCommand}">
    <b:Interaction.Triggers>
       <b:EventTrigger EventName="Click">
          <local:ClearTextTriggerAction Target="{Binding ElementName=FilterText}"/>
       </b:EventTrigger>
    </b:Interaction.Triggers>
    <Image Source="/VisionRanger;component/Images/Icons/icon.clear.dark.png" Stretch="UniformToFill" Margin="4,3,2,4" Opacity="0.5"/>
</Button>

The b XML namespace for XAML bahviors must be included.

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
∞觅青森が 2025-01-18 14:00:46

对我来说最明显的方法是创建一个自定义控件。但我需要一些可以快速用于客户项目的东西,因此我创建了一种样式,利用按钮的属性来创建搜索“按钮”(当然还涉及其他样式),但它们不会改变基本原则用过的。

无文本

当有文本时,单击关闭按钮会将其清除。

带文本

<!--#region Search Button-->
<Style
    x:Key="SearchButton"
    BasedOn="{StaticResource BaseStyle}"
    TargetType="{x:Type Button}">
    <Setter Property="Tag" Value="{StaticResource SearchIcon}" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ButtonBase}">
                <Border
                    x:Name="border"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="5"
                    SnapsToDevicePixels="True">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>

                        <!--#region Search Icon-->
                        <Border
                            Grid.Column="0"
                            Margin="{TemplateBinding Padding}"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center">
                            <Button
                                Name="icon"
                                Background="{TemplateBinding Background}"
                                Command="{TemplateBinding Command}"
                                CommandParameter="{Binding Text, ElementName=text}"
                                Content="{TemplateBinding Tag}"
                                FontSize="{TemplateBinding FontSize}"
                                Foreground="{TemplateBinding Foreground}"
                                IsDefault="True"
                                Style="{StaticResource IconButton}" />
                        </Border>
                        <!--#endregion-->

                        <!--#region Text Box-->
                        <Border Grid.Column="1" Margin="5">
                            <TextBox
                                Name="text"
                                VerticalAlignment="Center"
                                HorizontalContentAlignment="Left"
                                VerticalContentAlignment="Center"                                  
                                ClipToBounds="True"
                                FontSize="{TemplateBinding FontSize}"
                                Foreground="{TemplateBinding Foreground}"
                                Style="{StaticResource TextBoxWithPlaceHolder}"
                                Tag="{TemplateBinding Content}"
                                TextWrapping="NoWrap">
                                <TextBox.InputBindings>
                                    <KeyBinding
                                        Key="Enter"
                                        Command="{TemplateBinding Command}"
                                        CommandParameter="{Binding Text, ElementName=text}" />
                                </TextBox.InputBindings>
                            </TextBox>
                        </Border>
                        <!--#endregion-->

                        <!--#region Close Icon-->
                        <Button
                            Name="close"
                            Grid.Column="2"
                            Margin="5"
                            FontSize="{TemplateBinding FontSize}"
                            Foreground="{TemplateBinding Foreground}"
                            IsCancel="True"
                            Style="{StaticResource CloseButtonStyle}">
                            <TextBlock FontFamily="{StaticResource IconSolid}" Text="{StaticResource CloseIcon}" />
                        </Button>
                        <!--#endregion-->

                    </Grid>
                </Border>

                <!--#region Triggers-->
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Text, ElementName=text}" Value="">
                        <Setter TargetName="icon" Property="IsEnabled" Value="False" />
                        <Setter TargetName="close" Property="Visibility" Value="Collapsed" />
                    </DataTrigger>
                    <Trigger SourceName="close" Property="IsPressed" Value="True">
                        <Setter TargetName="text" Property="Text" Value="" />                           
                    </Trigger>
                </ControlTemplate.Triggers>
                <!--#endregion-->

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<!--#endregion-->

在代码中的任何一点,我定义一个按钮并在其上调用此样式,并绑定其命令。

<Button
       Width="400"
       Height="50"
       Margin="10"
       HorizontalAlignment="Left"
       Background="Transparent"
       Command="{Binding SearchCommand}"
       Style="{StaticResource SearchButton}" />

我相信有更好的方法可以做到这一点,但到目前为止这对我有用。

The obvious way for me is to create a custom control. But I needed something that I could use quickly for a client's project so I created a style that leveraged the properties of a button to create a search "button" (Of course there were other styles involved) but they don't change the underlying principle used.

Without Text

And when there is text, clicking the close button will clear it.

With Text

<!--#region Search Button-->
<Style
    x:Key="SearchButton"
    BasedOn="{StaticResource BaseStyle}"
    TargetType="{x:Type Button}">
    <Setter Property="Tag" Value="{StaticResource SearchIcon}" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ButtonBase}">
                <Border
                    x:Name="border"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    CornerRadius="5"
                    SnapsToDevicePixels="True">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>

                        <!--#region Search Icon-->
                        <Border
                            Grid.Column="0"
                            Margin="{TemplateBinding Padding}"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center">
                            <Button
                                Name="icon"
                                Background="{TemplateBinding Background}"
                                Command="{TemplateBinding Command}"
                                CommandParameter="{Binding Text, ElementName=text}"
                                Content="{TemplateBinding Tag}"
                                FontSize="{TemplateBinding FontSize}"
                                Foreground="{TemplateBinding Foreground}"
                                IsDefault="True"
                                Style="{StaticResource IconButton}" />
                        </Border>
                        <!--#endregion-->

                        <!--#region Text Box-->
                        <Border Grid.Column="1" Margin="5">
                            <TextBox
                                Name="text"
                                VerticalAlignment="Center"
                                HorizontalContentAlignment="Left"
                                VerticalContentAlignment="Center"                                  
                                ClipToBounds="True"
                                FontSize="{TemplateBinding FontSize}"
                                Foreground="{TemplateBinding Foreground}"
                                Style="{StaticResource TextBoxWithPlaceHolder}"
                                Tag="{TemplateBinding Content}"
                                TextWrapping="NoWrap">
                                <TextBox.InputBindings>
                                    <KeyBinding
                                        Key="Enter"
                                        Command="{TemplateBinding Command}"
                                        CommandParameter="{Binding Text, ElementName=text}" />
                                </TextBox.InputBindings>
                            </TextBox>
                        </Border>
                        <!--#endregion-->

                        <!--#region Close Icon-->
                        <Button
                            Name="close"
                            Grid.Column="2"
                            Margin="5"
                            FontSize="{TemplateBinding FontSize}"
                            Foreground="{TemplateBinding Foreground}"
                            IsCancel="True"
                            Style="{StaticResource CloseButtonStyle}">
                            <TextBlock FontFamily="{StaticResource IconSolid}" Text="{StaticResource CloseIcon}" />
                        </Button>
                        <!--#endregion-->

                    </Grid>
                </Border>

                <!--#region Triggers-->
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Text, ElementName=text}" Value="">
                        <Setter TargetName="icon" Property="IsEnabled" Value="False" />
                        <Setter TargetName="close" Property="Visibility" Value="Collapsed" />
                    </DataTrigger>
                    <Trigger SourceName="close" Property="IsPressed" Value="True">
                        <Setter TargetName="text" Property="Text" Value="" />                           
                    </Trigger>
                </ControlTemplate.Triggers>
                <!--#endregion-->

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<!--#endregion-->

At any point in code, I define a button and call this style on it, and bind its command.

<Button
       Width="400"
       Height="50"
       Margin="10"
       HorizontalAlignment="Left"
       Background="Transparent"
       Command="{Binding SearchCommand}"
       Style="{StaticResource SearchButton}" />

I believe there are better ways to do this but this has worked for me by far.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文