数据触发器没有触发正确的字符串值
本文关键字:字符串 触发器 数据 | 更新日期: 2023-09-27 18:06:55
思路是这样的。如果文本框为空,"DataTrigger"应该将轮廓(BorderBrush)设置为红色。如果文本框不是空的/有文本;那么dataTrigger应该将BorderBrush设置为蓝色。
xmlns:conv="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!-- conv is referenced in the "clr-namespace:WpfApplication1" namespace. It's bassically a referal to a converter I'm using -->
<conv:IsNullConverter x:Key="isNullConverter"/>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<!-- if the textbox is empty, then the setter should set the border colour to red-->
<DataTrigger Binding="{Binding Words, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource isNullConverter}}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<!-- If it has text inside it, setter should set the border colour to blue -->
<DataTrigger Binding="{Binding Words, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource isNullConverter}}" Value="False">
<Setter Property="BorderBrush" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBox x:Name="first" FontSize="14" TabIndex="1" Background="Black" BorderThickness="5" Foreground="White" Margin="29,10,132,272" />
</Grid>
因为数据触发器不可能单独查看一个值是否为非空,所以我必须添加一些代码来帮助它。
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;
namespace WpfApplication1
{
public class IsNullConverter : IValueConverter, INotifyPropertyChanged
{
// The string that the 'conv:' checks against
private string FOO;
// The DataTriggrer is bound to 'Words'
public string Words
{
get
{
return FOO;
}
set
{
if (FOO != value)
{
FOO = value;
RaisePropertyChanged("Words");
}
}
}
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged == null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public string Error
{
get { return null; }
}
// This is the 'Convert' Parameter conv checks against. Here is the problem is
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//This checks against the FOO string at the top of this class. Not the FOO in 'Words' get & set string
if (FOO == null)
{
value = true;
}
// So even if 'Words' raises the property changed, The origional FOO string remains unaffected.
// So the Datatrigger is never fired
if (FOO != null)
{
value = false;
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullConverter can only be used OneWay.");
}
}
}
问题是,如果我在字符串FOO后面加上;
private string FOO = "Something";
Datatrigger在运行时触发并将轮廓颜色更改为蓝色。但是,我需要的颜色是基于文本框的内容,而不是我直接声明字符串作为。
我尝试将数据触发器绑定到'Words'字符串,但轮廓颜色仍然是红色,空或不。
和建议吗?如果有更好的方法,我真的不介意把这段代码完全颠倒过来。
给你:
<TextBox x:Name="first" FontSize="14" TabIndex="1" Background="Black" BorderThickness="5" Foreground="White" Margin="29,10,132,272">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="BorderBrush" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="{x:Null}">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
使用RelativeSource
:
TextBox.Text
属性<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource isNullConverter}}" Value="True">
<!--apropriate setter-->
</DataTrigger>
如果Text
为空,则设置BorderBrush
。当Text
不为空时设置边框刷,只需使用正常的Setter
,不使用DataTrigger
。
另外,请注意在ValueConverter
中应该使用String.IsNullOrEmpty
而不是普通的NULL比较。
您可以简化您的转换器,使其看起来像
public class IsNullConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return String.IsNullOrEmpty((string) value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullConverter can only be used OneWay.");
}
}
,然后样式绑定TextBox.Text
通过转换器
<Window.Resources>
<conv:IsNullConverter x:Key="isNullConverter"/>
<Style TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text, Converter={StaticResource isNullConverter}}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
这将工作,但只有当TextBox
不集中时,默认模板将接管并更改BorderBrush
。你可以让它工作,但是你需要改变默认模板,最简单的模板是在Style
Setter
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>