Измените цвет шрифта TextRange, но не текст, который будет написан рядом с ним. - PullRequest
0 голосов
/ 02 мая 2020

Я использую TextRanges в WPF RichTextBox, и я хочу изменить цвет шрифта TextRange, но если в этом случае рядом с ним написан текст, он имеет оригинальный цвет. Например, у меня есть RichTextBox с именем richTextBox с черным цветом шрифта, и я использую этот код:

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

Я хочу, чтобы, если после выполнения этого кода кто-то добавил текст в richTextBox, он был написан на черный, а не синий. Есть какой-либо способ сделать это? Спасибо!

Ответы [ 2 ]

0 голосов
/ 03 мая 2020

Я думаю, что подход Остаса сработает. Я просто хотел бы предложить простой обходной путь.

Это добавить пробел в конце 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(" ");
0 голосов
/ 03 мая 2020

Я не думаю, что вы можете установить его напрямую, чтобы следующий символ был другого цвета. (Кто-то, пожалуйста, исправьте меня, если вы знаете, как).

Но вы могли бы подписаться на TextChangedEvent вашего RichTextBox и применить новый цвет переднего плана, когда пользователь добавляет немного текста в конце.

Однако сложная часть состоит в том, чтобы определить, сколько было изменено, чтобы вы могли применить новый передний план только к этой части, и узнать, были ли внесены изменения в тех местах, которые были сделаны в конце текста.

Где вы выполняете код для установки синего цвета переднего плана:

  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)"));
    }

Источник очень полезного выражения регулярного выражения { ссылка }

В событии 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 .Изменения: https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.textchangedeventargs.changes?view=netcore-3.1#System_Windows_Controls_TextChangedEventArgs_Changes

...