我想实现一些带有循环图标和占位符的自定义搜索文本框。因此,我创建了一个自定义控件模板,其中有用于循环图标的 TextBlock(我使用了特定字体中的一些符号)、ScrollViewer(它是显示文本的默认 TextBox 模板中的默认控件)、带有一些文本“搜索”的 TextBlock占位符(当我的文本框聚焦或用户写入内容时不可见)和按钮(当文本框为空时不可见,当用户写入内容时可见,应在单击时清除文本框的文本)。这是它的样子:
这是该控制模板的代码:
<ControlTemplate x:Key="SearchTextBoxTemplate" TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5"
SnapsToDevicePixels="True">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="6,1,6,0"
Grid.Column="0"
FontFamily="{Binding Font, Source={StaticResource Icons}}"
FontSize="{TemplateBinding FontSize}"
Foreground="#8C8C8C"
FontWeight="Normal"
Text=""
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<TextBlock x:Name="Placeholder"
Grid.Column="1"
FontSize="{TemplateBinding FontSize}"
Focusable="False"
Text="Search"
Foreground="#AAAFB4"
IsHitTestVisible="False"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Visibility="Collapsed"/>
<ScrollViewer x:Name="PART_ContentHost"
Grid.Column="1"
Focusable="False"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
VerticalContentAlignment="Center"
VerticalAlignment="Center"/>
<Button x:Name="ClearSearchText"
Margin="5,0,6,0"
Grid.Column="2"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Cursor="Hand"
FontFamily="{Binding Font, Source={StaticResource ResourceKey=Icons}}"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Button.Content>
<Grid>
<TextBlock FontSize="12"
Foreground="#D1D1D1"
Text=""/>
<TextBlock FontSize="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
Text=""/>
</Grid>
</Button.Content>
</Button>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.6"/>
</Trigger>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter TargetName="ClearSearchText" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter TargetName="ClearSearchText" Property="Visibility" Value="Collapsed"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
<Condition Property="Text" Value="{x:Static sys:String.Empty}"/>
</MultiTrigger.Conditions>
<Setter TargetName="Placeholder" Property="Visibility" Value="Visible"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
<Condition Property="Text" Value="{x:Null}"/>
</MultiTrigger.Conditions>
<Setter TargetName="Placeholder" Property="Visibility" Value="Visible"/>
</MultiTrigger>
<Trigger SourceName="ClearSearchText" Property="IsPressed" Value="True">
<Setter Property="Text" Value="{x:Null}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
一切正常。但是,我仍然无法编写正确的逻辑,通过单击按钮来清除 TextBox 的文本。我想在 XAML 模板中执行此操作,而不添加一些新的后端代码或创建自定义用户控件。
正如您在 ControlTemplate.Triggers 组末尾所看到的,我尝试添加一个触发器,以在按下按钮时清除文本。但它不起作用:
<Trigger SourceName="ClearSearchText" Property="IsPressed" Value="True">
<Setter Property="Text" Value="{x:Null}"/>
</Trigger>
此外,我尝试将相同 Button 属性的检查添加到 Button 样式:
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
.... Some setter
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
但是我不知道如何从放置此按钮的父控件模板中正确获取 Text 属性。
那么如何正确执行此操作以及如何通过单击按钮清除文本?
使用Microsoft.Xaml.Behaviors.Wpf的EventTrigger和ChangePropertyAction,您可以在触发Button.Click事件时设置TextBox.Text属性。
<Button x:Name="ClearSearchText"
...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
PropertyName="Text" Value="{x:Null}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
顺便说一下,如果目标是 TextBlock.Text 属性,您还可以使用普通的 EventTrigger 和 StringAnimationUsingKeyFrames。但它不适用于 TextBox.Text 属性,因为它不可设置动画。