你能暂时 disable/override 控制 WPF 中的模板触发器吗?
Can you temporarily disable/override Control Template Triggers in WPF?
如果我在其中输入无效文本,我正在设置 TextBox 的 BorderBrush:
if (!Regex.IsMatch(txtAddName.Text, @"[^A-Za-z0-9|()& ]"))
{
txtAddName.BorderBrush = regularBrush;
}
else
{
txtAddName.BorderBrush = errorBrush;
}
然而,我设置的 BorderBrush 被 Control Template Triggers 覆盖:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</Trigger>
</ControlTemplate.Triggers>
所以我需要以某种方式禁用它们,直到我失去 TextBox 的焦点或文本有效。我考虑过用它制作一个 Multitrigger 并设置第二个条件,但我无法想象这个条件应该是什么样子。有没有一种简单的方法可以做到这一点?还没有找到任何有用的东西。
有没有这样的可能:
在代码设置中 bool:
bool isTextInvalid;
if (!Regex.IsMatch(txtAddName.Text, @"[^A-Za-z0-9|()& ]"))
{
txtAddName.BorderBrush = regularBrush;
isTextInvalid = false;
}
else
{
txtAddName.BorderBrush = errorBrush;
isTextInvalid = true;
}
然后在 XAML 中访问这个 bool ?
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="isTextInvalid" Value="False"/> <-- The bool from code
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
您可以使用 Tag
属性 来存储 isTextInvalid
的当前值:
txtAddName.BorderBrush = regularBrush;
txtAddName.Tag = false;
XAML:
<MultiTrigger xmlns:sys="clr-namespace:System;assembly=mscorlib">
<MultiTrigger.Conditions>
<Condition Property="Tag">
<Condition.Value>
<sys:Boolean>false</sys:Boolean>
</Condition.Value>
</Condition>
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</MultiTrigger.Setters>
</MultiTrigger>
如果您的 TextBox 的文本有效性优先于其他触发器,您可以使用 ValueConverter
、带触发器(无 ControlTemplate 触发器)且无代码隐藏的 Style
来完成这一切。
这是一个工作示例:
MainWindow.xaml:
<Window.Resources>
<local:MyRegexValueConverter x:Key="MyRegexConverter"/>
</Window.Resources>
<Grid>
<TextBox x:Name="txtAddName" Width="300" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="MinWidth" Value="120" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Name="Border" CornerRadius="2" Padding="2" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}">
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#505F69"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="#505F69"/>
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Text,Converter={StaticResource MyRegexConverter}}" Value="True"
<Setter Property="BorderBrush" Value="#FF0000"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
MainWindow.xaml.cs:
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
MyRegexValueConverter.cs:
public class MyRegexValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var textValue = System.Convert.ToString(value);
// Returns true if text is invalid, otherwise false
return Regex.IsMatch(textValue, @"[^A-Za-z0-9|()& ]");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
使用 IsMouseOver 或 IsFocused 的示例输出:
带有无效文本的示例输出:
我在一个新的 WPF 项目中对此进行了测试,它可以正常工作。希望你觉得它有用。
如果我在其中输入无效文本,我正在设置 TextBox 的 BorderBrush:
if (!Regex.IsMatch(txtAddName.Text, @"[^A-Za-z0-9|()& ]"))
{
txtAddName.BorderBrush = regularBrush;
}
else
{
txtAddName.BorderBrush = errorBrush;
}
然而,我设置的 BorderBrush 被 Control Template Triggers 覆盖:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</Trigger>
</ControlTemplate.Triggers>
所以我需要以某种方式禁用它们,直到我失去 TextBox 的焦点或文本有效。我考虑过用它制作一个 Multitrigger 并设置第二个条件,但我无法想象这个条件应该是什么样子。有没有一种简单的方法可以做到这一点?还没有找到任何有用的东西。
有没有这样的可能:
在代码设置中 bool:
bool isTextInvalid;
if (!Regex.IsMatch(txtAddName.Text, @"[^A-Za-z0-9|()& ]"))
{
txtAddName.BorderBrush = regularBrush;
isTextInvalid = false;
}
else
{
txtAddName.BorderBrush = errorBrush;
isTextInvalid = true;
}
然后在 XAML 中访问这个 bool ?
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="isTextInvalid" Value="False"/> <-- The bool from code
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
您可以使用 Tag
属性 来存储 isTextInvalid
的当前值:
txtAddName.BorderBrush = regularBrush;
txtAddName.Tag = false;
XAML:
<MultiTrigger xmlns:sys="clr-namespace:System;assembly=mscorlib">
<MultiTrigger.Conditions>
<Condition Property="Tag">
<Condition.Value>
<sys:Boolean>false</sys:Boolean>
</Condition.Value>
</Condition>
<Condition Property="IsFocused" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="Border" Property="BorderBrush" Value="#505F69"/>
</MultiTrigger.Setters>
</MultiTrigger>
如果您的 TextBox 的文本有效性优先于其他触发器,您可以使用 ValueConverter
、带触发器(无 ControlTemplate 触发器)且无代码隐藏的 Style
来完成这一切。
这是一个工作示例:
MainWindow.xaml:
<Window.Resources>
<local:MyRegexValueConverter x:Key="MyRegexConverter"/>
</Window.Resources>
<Grid>
<TextBox x:Name="txtAddName" Width="300" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="MinWidth" Value="120" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Name="Border" CornerRadius="2" Padding="2" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}">
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#505F69"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="#505F69"/>
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Text,Converter={StaticResource MyRegexConverter}}" Value="True"
<Setter Property="BorderBrush" Value="#FF0000"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
MainWindow.xaml.cs:
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
MyRegexValueConverter.cs:
public class MyRegexValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var textValue = System.Convert.ToString(value);
// Returns true if text is invalid, otherwise false
return Regex.IsMatch(textValue, @"[^A-Za-z0-9|()& ]");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
使用 IsMouseOver 或 IsFocused 的示例输出:
带有无效文本的示例输出:
我在一个新的 WPF 项目中对此进行了测试,它可以正常工作。希望你觉得它有用。