【问题标题】:display formatting marks for WPF RichtextBox显示 WPF RichtextBox 的格式标记
【发布时间】:2025-12-17 09:45:02
【问题描述】:

看来我之前的问题不太清楚。所以我重新定义它:我有一个富文本框(WPF,C#),我希望当用户在运行时在其中键入文本时,动态显示格式标记。也就是说,用点替换空格,用 -> 替换制表符,用 MSWord 的相应标记替换段尾。在这里,我希望得到什么:

【问题讨论】:

  • 您需要使用 IValueConverter 来更改文本以截取控件和模型之间的值,尽管这也可以在 viewModel 中完成,其中格式化文本和实际文本由绑定属性
  • 是这个领域的初学者,能否请您说的更清楚些。此外,我希望格式标记保持不可打印,并保持文本换行。
  • 只是为您创建一个示例
  • 非常感谢这个例子,但是当我照原样复制并粘贴它时,我有以下错误:“名称空间中不存在 TextFormatter 和 VM:clr-namespace: WPF_ScratchPad”。请问如何克服这个问题。
  • 你需要将你的类包装在我使用的命名空间namespace WPF_ScratchPad 你可以使用任何你想要的,只要确保你的x:Class="WPF_ScratchPad.MainWindowxmlns:local="clr-namespace:WPF_ScratchPad" 对你来说是正确的

标签: wpf formatting richtextbox


【解决方案1】:

你可以使用你的虚拟机来格式化这个庄园,也可以使用 IValueConverter

例如

XAML

<Window x:Class="WPF_ScratchPad.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:local="clr-namespace:WPF_ScratchPad"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:TextFormatter x:Key="TextFormatter"/>
    </Window.Resources>
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>
    <StackPanel>
        <GroupBox Header="Stored Text">
            <TextBox MaxLines="50" MinLines="5" Text="{Binding Text}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap" />
        </GroupBox>
        <GroupBox Header="Converter Formatter">
            <TextBox MaxLines="50" MinLines="5" Text="{Binding Text, Converter={StaticResource TextFormatter}}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap" />
        </GroupBox>

        <CheckBox IsChecked="{Binding ShowForattnig}">Show Format Marks</CheckBox>
        <GroupBox Header="VM Formatted">
            <TextBox MaxLines="50" MinLines="5" Text="{Binding DisplayText}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap" />
        </GroupBox>
    </StackPanel>
</Window>

查看模型

public class VM:BindableBase
{
    public TextFormatter Formmatter { get; } = new TextFormatter();
    private string _Text;

    public string Text
    {
        get { return _Text; }
        set
        {
            if(SetProperty(ref _Text, value))
            {
                RaisePropertyChanged(nameof(DisplayText));
            }
        }
    }


    public string DisplayText
    {
        get
        {
            if (ShowForattnig)
                return Formmatter.Convert(Text);
            else
                return Text;
        }
        set
        {
            if (ShowForattnig)
                Text = Formmatter.ConvertBack(value);
            else
                Text = value;

        }
    }


    private bool _ShowForattnig;

    public bool ShowForattnig
    {
        get { return  _ShowForattnig; }
        set
        {
            if(SetProperty(ref _ShowForattnig, value))
            {
                RaisePropertyChanged(nameof(Text));
                RaisePropertyChanged(nameof(DisplayText));
            }
        }
    }

}

注意:因为我一直在做值转换器,所以我已经引用了它,但你可以直接将代码放入

值转换器

public class TextFormatter : IValueConverter
{
    public Dictionary<string, string> Replacements { get; } = new Dictionary<string, string>()
    {
        {Environment.NewLine,$"¶{Environment.NewLine}" },
        {" ","•" }
    };
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => Convert(value?.ToString());

    public string Convert(string value)
    {
        StringBuilder format = new StringBuilder( value);
        foreach (var item in Replacements)
        {
            format = format.Replace(item.Key, item.Value);
        }
        return format.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => ConvertBack(value?.ToString());

    public string ConvertBack(string value)
    {
        StringBuilder format = new StringBuilder(value);
        foreach (var item in Replacements)
        {
            format = format.Replace(item.Value, item.Key);
        }
        return format.ToString();
    }
}

注意:此处将 Prism 用于样板

【讨论】:

  • 非常感谢 MikeT !现在可以了!但是,格式标记是可打印的(即,当我将键入的文本从文本框中复制粘贴到 MSWord 时,标记也会被粘贴)。我们可以用装饰器在另一层上显示格式标记,使它们不可打印吗?
  • 您必须覆盖默认的复制粘贴行为,请参阅msdn.microsoft.com/en-us/library/…
  • 也许可以用 Adorners 来做到这一点,我还没有研究过,但我肯定会说你需要提高对基础知识的掌握,然后再继续使用更高级的功能
  • 非常感谢迈克的帮助!