我在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中添加文字,它将以黑色书写,而不是蓝色。有什么办法可以做到这一点吗?
我不认为你可以直接设置它,使下一个字符的颜色不同。(如果你知道如何设置,请纠正我)。
但你可以做的是订阅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;
}
我认为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(" ");