Как отформатировать RichTextBox с существующим содержимым - PullRequest
3 голосов
/ 10 июля 2019

Я получаю данные из веб-API, который возвращает текст и форматирует информацию. Данные форматирования включают только тип форматирования (полужирный, курсив и т. Д.) И диапазон этого форматирования. Основная проблема в том, что два диапазона могут «сталкиваться» (например, первые 3 символа слова выделены жирным шрифтом и курсивом, а последние 3 символа - только курсивом). Пример ответа

{
  "text" : "This is an example text",
  "inlineStyles" : [
    {
      "offsetFromStart" : 5,
      "length" : 10,
      "type" : "bold"
    }
    {
      "offsetFromStart" : 10,
      "length" : 10,
      "type" : "italic"
    }
  ]
}

Я уже пытался сделать это с простым TextBlock и потерпел неудачу. И я также попробовал это с RichTextBox, но когда я добавил Span, я не мог вставить его в исходное положение. Я также думал о форматировании каждого символа с его собственным диапазоном или прогоном, но это было бы очень некрасиво и в общем просто плохое решение. (Мое главное беспокойство - скорость ..)

var tb = new RichTextBox();
var para = new Paragraph();
para.Inlines.Add("This is an example text") // Text parsed from the response

var startingPointer1 = para.ContentStart.GetPositionAtOffset(5);
var sp1 = new Span(startingPointer1, startingPointer1.GetPositionAtOffset(10));
sp1.FontWeight = FontWeights.Bold;

var startingPointer2 = para.ContentStart.GetPositionAtOffset(10);
var sp2 = new Span(startingPointer2 , startingPointer2 .GetPositionAtOffset(10));
sp2.FontStyle= FontStyles.Italic;

para.Inlines.Add(sp1);
para.Inlines.Add(sp2);
tb.Document.Blocks.Add(para);

Этот код добавляет его в конец, и при объединении нескольких встроенных элементов, как в моем примере, он вообще не работает (из-за первой проблемы.)

Пример результата: example image

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Я не думаю, что вы можете перекрывать прогоны / пролеты, как это, вам придется найти все точки разрыва в вашем тексте и отформатировать каждый текстовый диапазон отдельно. Это похоже на HTML, где

<bold>some<italic> bold italic</bold> and other </italic> text.

недействительно. В вашем случае у вас будет жирный шрифт из (5,10), жирный шрифт из (11, 15) и т. Д.

Вероятно, полезно найти какой-нибудь класс Range с методами для объединения диапазонов, разделения, поиска перекрытий и т. Д. Некоторое время назад я начал с this .

РЕДАКТИРОВАТЬ: У меня точно нет идеи, как реализовать все это (в прошлый раз я делал нечто подобное было почти 10 лет назад), но вы можете попробовать что-то вроде этого:

  1. Создать List<Range<int>>. Первоначально он содержит один диапазон (0, длина текста).
  2. Загрузить первый стиль, создать новый диапазон с начальным / конечным смещением. Перекрыть (или любой другой метод, который подходит) этот диапазон с диапазоном в списке. Это должно дать вам 3 диапазона, что-то вроде (0, start of style), (start of style, end of style), (end of style, end of text). Удалить старый диапазон из списка и добавить новые.
  3. Загрузите следующее, найдите перекрытия с диапазонами в списке, удалите перекрывающиеся и добавьте новые диапазоны.
  4. Это должно дать вам список непересекающихся диапазонов.
  5. Теперь по стилям. Вы можете создать своего рода класс таблицы стилей. Этот класс может использовать FontWeights, FontStyles и другие перечисления, определенные в System.Windows. Измените список так, чтобы он содержал, например, List<Tuple<int, Stylesheet>>. Для вычисления перекрытий просто используйте первый параметр в кортеже.
  6. Прежде чем удалять старые диапазоны из списка, объедините стили.
  7. Это должно дать вам список не перекрывающихся областей с соответствующими стилями. Создать TextRange s, применить стили

Другая идея, которая может сработать:

  1. Снова создайте таблицу стилей. Изначально это должен быть нормальный вес, нормальный стиль, размер шрифта по умолчанию и т. Д.
  2. Найдите следующее смещение на входе (первое, которое больше текущего), создайте TextRange и примените стиль.
  3. Найти следующее смещение от входа, изменить текущий (и только) стиль и применить.

Если я правильно помню, вставка определения стиля в текст также считается как символы, поэтому вам может потребоваться скорректировать смещения при вставке тегов стиля в окончательный текст. Кроме того, я считаю, что это выполнимо просто с помощью TextBlock.

Как я уже сказал, я не знаю, работает ли это так, как описано, но это может дать вам и идею.

0 голосов
/ 13 июля 2019

Мое текущее решение состоит в том, что я перебираю каждый символ один за другим и сканирую диапазоны, определяя, есть ли текущий символ в каком-либо из них, и затем назначая диапазон для символа.Это не идеально для всех, но оно выполняет свою работу.Я постараюсь реализовать фактический алгоритм для этого позже.До этого, если у вас есть любая информация, которая может помочь, пожалуйста, прокомментируйте.

Если кому-то понадобится пример кода моей текущей реализации, я с радостью поделюсь им с вами.(Хотя это не совсем эффективно)

...