改变TextRange字体的颜色,但不改变旁边的文字。

问题描述 投票:0回答:1

我在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中添加文字,它将以黑色书写,而不是蓝色。有什么办法可以做到这一点吗?

c# wpf xaml richtextbox textrange
1个回答
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)"));
    }

非常有用的regex表达式的来源https:/stackoverflow.coma198231713448212。

在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.comen-usdotnetapisystem.windows.controls.textchangedeventargs.changes?view=netcore-3.1#System_Windows_Controls_TextChangedEventArgs_Changes。


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(" ");
© www.soinside.com 2019 - 2024. All rights reserved.