根据特定的凝视和结束标记更改文本框前景色

时间:2018-07-30 11:00:02

标签: c# wpf xaml textbox wpf-controls

enter image description here我正在开发WPF应用程序,在其中使用Textbox编写一些文本。每当用户用<qs>(在开始时)和<qe>在结尾时将文本框中的特定文本括起来时,我想将文本框的前景色更改为红色。类似地,如果用户将某些文本括在开头<as>并在结尾<ae>处,则文本颜色应更改为绿色。我在网上搜索了很多内容,但没有找到任何信息。我们非常感谢您的帮助。

预期输出如图所示

此外,我在应用程序中使用了MVVM。

1 个答案:

答案 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中始终包含转换器的实例,此外,如果您需要一些更多的自定义行为,那么您只需将该行为添加到自定义控件中,而不用编写许多其他转换器。