0

我在 WPF RichTextBox 中使用 TextRanges 并且我想更改 TextRange 的字体颜色,但是如果它旁边写有文本,则它具有原始颜色。例如,我有一个名为richTextBox 的 RichTextBox,字体颜色为黑色,我使用以下代码:

TextPointer start = richTextBox.Document.ContentStart;
TextPointer end = richTextBox.Document.ContentEnd;
new TextRange(start, end).ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Blue);

我希望,如果在执行此代码后,有人将文本添加到richTextBox,它是用黑色而不是蓝色写的。有没有办法做到这一点?谢谢!

4

2 回答 2

0

我认为 Ostas 的方法会奏效。我只想建议一个简单的解决方法。

就是在改变颜色的时候在RichTextBox的末尾加一个空格。之后,如果有人在现有文本之后立即添加新文本,则颜色将为蓝色。如果有人在末尾添加新文本(在空格之后),颜色将是默认值。

TextPointer start = textBox.Document.ContentStart;
TextPointer end = textBox.Document.ContentEnd;

var range = new TextRange(start, end);
range.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Blue);

if (textBox.Document.Blocks.LastBlock is Paragraph paragraph)
    paragraph.Inlines.Add(" ");
于 2020-05-03T00:44:42.710 回答
0

我认为您不能直接设置它,以便下一个字符具有不同的颜色。(如果你知道如何,请有人纠正我)。

但是您可以做的是订阅 RichTextBox 的 TextChangedEvent 并在用户最后添加一些文本时应用新的前景色。

然而,棘手的部分是检测更改了多少,以便您可以仅将新前景应用于该部分,并了解更改是否在文本末尾完成。

在哪里执行将前景设置为蓝色的代码:

  TextPointer start = this.RTextBox.Document.ContentStart;
  TextPointer end = this.RTextBox.Document.ContentEnd;
  TextRange textRange = new TextRange(start, end);
  textRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Blue);
  //Storing the text to allow for comparison later
  this.textSaved = textRange.Text;
  this.wasTextColorInitialized = true;

添加了变量和新方法:

    private bool wasTextColorInitialized = false;

    private string textSaved;

    /// <summary>
    /// Remove some of the invisible caracter in a string to allowe for comparison
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    private string GetComparableString(string text)
    {
        return string.Join(string.Empty, Regex.Split(text, @"(?:\r\n|\n|\r)"));
    }

非常有用的正则表达式的来源 https://stackoverflow.com/a/1982317/13448212

在 textChanged 事件中,您必须检查更改是否是由于用户添加文本,然后确定是否在文本末尾进行了更改:

private void RTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TextPointer endOfDoc = this.RTextBox.Document.ContentEnd;
        TextPointer startOfDoc = this.RTextBox.Document.ContentStart;
        TextRange fullRange = new TextRange(startOfDoc, endOfDoc);

        string newText = fullRange.Text;

        //e.Changes.Count = 0 means that only a Property was changed (eg Foreground)
        if (this.wasTextColorInitialized && e.Changes.Count != 0)
        {
            int lengthOfTextAdded = newText.Length - this.textSaved.Length;
            //The text can end with "\r\n" and the text added will be before this hence the "GetComparableString" method
            if (lengthOfTextAdded > 0 && newText.StartsWith(this.GetComparableString(this.textSaved)))
            {
                //in e.Changes, the changes are ordered, the latest being the furthest in the text
                TextRange rangeOfTextAdded = new TextRange(endOfDoc.GetPositionAtOffset(-e.Changes.Last().AddedLength), endOfDoc);
                rangeOfTextAdded.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
            }
            else
            {
                //Nothing to do
            }
        }
        else
        {
            //Nothing to do
        }
        this.textSaved = newText;
    }

e.Changes 的文档:https ://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.textchangedeventargs.changes?view=netcore-3.1#System_Windows_Controls_TextChangedEventArgs_Changes

于 2020-05-03T00:03:55.837 回答