我正在开发WPF应用程序,在其中使用Textbox编写一些文本。每当用户用<qs>
(在开始时)和<qe>
在结尾时将文本框中的特定文本括起来时,我想将文本框的前景色更改为红色。类似地,如果用户将某些文本括在开头<as>
并在结尾<ae>
处,则文本颜色应更改为绿色。我在网上搜索了很多内容,但没有找到任何信息。我们非常感谢您的帮助。
预期输出如图所示
此外,我在应用程序中使用了MVVM。
答案 0 :(得分:0)
正如@Erno de Weerd所评论的那样,您可以为此使用自定义ValueConvertert。我可以想到的另一种方法是继承TextBox
并覆盖TextProperty
元数据以对该属性的更改做出反应。下面的示例包含两种方法:
XAML:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpfApp="clr-namespace:WpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<wpfApp:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<wpfApp:TextToColorConverter x:Key="TextToColorConverter"/>
</Window.Resources>
<StackPanel >
<TextBox Text="{Binding SomeString, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding SomeString, Mode=OneWay, Converter={StaticResource TextToColorConverter}}"
Margin="0,0,0,20"/>
<wpfApp:MyCustomTextBox Text="{Binding SomeString, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Window>
MainWindowViewModel仅包含bound属性并实现INotifyPropertyChanged:
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _someString;
public string SomeString
{
get => _someString;
set
{
if (value == _someString) return;
_someString = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
第一种方法,即IValueConverter:
public class TextToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var str = (string)value;
if (str == null) return new SolidColorBrush(Colors.Black);
return str.StartsWith("<qs>") && str.EndsWith("<qe>") ? new SolidColorBrush(Colors.Red) :
str.StartsWith("<as>") && str.EndsWith("<ae>") ? new SolidColorBrush(Colors.Green) :
new SolidColorBrush(Colors.Black);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
第二个,我们继承自TextBox:
public class MyCustomTextBox : TextBox
{
static MyCustomTextBox()
{
TextProperty.OverrideMetadata(typeof(MyCustomTextBox), new FrameworkPropertyMetadata(OnTextChanged));
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (MyCustomTextBox)d;
var str = (string)e.NewValue;
SolidColorBrush foreGround;
if (str == null)
{
foreGround = new SolidColorBrush(Colors.Black);
}
else
{
foreGround = str.StartsWith("<qs>") && str.EndsWith("<qe>") ? new SolidColorBrush(Colors.Red) :
str.StartsWith("<as>") && str.EndsWith("<ae>") ? new SolidColorBrush(Colors.Green) :
new SolidColorBrush(Colors.Black);
}
control.Foreground = foreGround;
}
}
我个人更喜欢第二种方法,创建自己的自定义控件使我可以在任意数量的视图中使用该控件,而无需在XAML中始终包含转换器的实例,此外,如果您需要一些更多的自定义行为,那么您只需将该行为添加到自定义控件中,而不用编写许多其他转换器。