Edit: я обнаружил в другом ответе, что TextBlock
также имеет коллекцию Inlines
, к которой можно добавить Run
s. Ответ Анваки изобретательно использует присоединенное свойство как своего рода конвертер.
У меня была пара идей о том, как подойти к этому. Только один будет правильно обрабатывать перенос слов и обрабатывать символы разными шрифтами.
Используйте FlowDocumentScrollViewer
и привяжите к нему строку, используя ValueConverter
, который преобразует строку в FlowDocument
.
<FlowDocumentScrollViewer
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Document="{Binding MyString, Converter={StaticResource MyConverter}}" />
Вы можете создать свойства в конвертере, чтобы установить обычные свойства шрифта, которые не могут быть установлены в FlowDocumentScrollViewer
и должны быть установлены в FlowDocument
, который создает конвертер. Возможно, вам также понадобятся некоторые свойства Font для подстрок исключений, которым нужен другой шрифт (и, возможно, другой размер). Другой вариант - создать Binding
s на FlowDocument
для некоторых из этих свойств (RelativeSource
).
А вот как вы создаете FlowDocument
в коде:
FlowDocument doc = new FlowDocument();
doc.FontFamily = new FontFamily( "Our Own Font" );
Paragraph par = new Paragraph();
doc.Blocks.Add( par );
Затем вам нужно будет разбить входящую строку на специальные подстроки, сохраняя эти подстроки нетронутыми. Вам нужно будет свернуть свой собственный сплиттер и получить коллекцию подстрок в конвертере или в конвертере.
Добавить нормальную подстроку к абзацу:
Run r = new Run( substring );
par.Inlines.Add( r );
Добавить специальную подстроку к абзацу с другим шрифтом:
Run r = new Run( substring );
r.FontFamily = new FontFamily( "Arial" );
par.Inlines.Add( r );
Выше приведены только маленькие фрагменты. Я не знаю, как вы хотите подходить к разбиению строки или итерации по подстрокам, так как я не знаком с данными, поэтому я не предоставлял метод, который я собрал вместе, чтобы посмотреть, сработает ли моя идея. Вы также можете использовать Dictionary
, чтобы обнаружить одну подстроку и использовать замену в выводе, такую как обнаружение "(SM)"
и замена его на "℠"
.
Дайте мне знать, если у вас есть какие-либо вопросы или есть что-то, что я могу уточнить.
(Хорошо, что вы сказали, что это только для чтения. RichTextBox
не будет работать, потому что его свойство Document
не является DependencyProperty
и, следовательно, не может быть целью Binding
. Хотя, можно было бы использовать Mode=OneWayToSource
, чтобы изменить его, применяя ConvertBack
вместо Convert
.)
«Я думаю, что то, что вы пропустили (перебирая строку и создавая эти прогоны), является сложной частью».
Я действительно очень кратко рассказал о разбиении строки на специальные подстроки. Когда я сказал: «Я не знаю, как вы разбиваете строку», я не говорил, что понятия не имею, как это сделать вообще (я перефразировал), но я понятия не имел, как бы вы хотели справиться с этим. Я предположил, что вам не составит труда разобраться в этой части, потому что это проблема манипуляции со строками, с которой я мог бы разобраться. Это, и вы можете обнаружить крайние случаи среди ваших данных, которые требуют изменений в том, как вы их обрабатываете.
Я опишу вам относительно грубую версию, используя IndexOf()
и Substring()
.
Итак, вот проблема внутри проблемы: у вас есть много строк (например, "Company Name(R), makers of Product(TM)"
), которые содержат 0 или более специальных подстрок. Эти подстроки немногочисленны и известны, и входная строка должна быть разбита на несколько строк, где специальные и нестандартные подстроки были изолированы друг от друга (например, {"Company Name", "(R)", ", makers of Product", "(TM)"}
).
Специальные подстроки немногочисленны и известны, поэтому вам нужен их массив. По возвращаемому значению .IndexOf()
вы знаете, найдена ли подстрока или нет. Зацикливаясь на известных специальных подстроках, вы можете найти первый экземпляр любой из них со сравнением индексов, за исключением длины подстроки.
Каждый раз, когда вы находите самую раннюю специальную подстроку в строке S
(если есть), вы создаете производные строки A
, B
и C
. B
- специальная подстрока, A
и C
- до и после. Добавьте A
и B
к List
, и C
станет новым S
, и вы сделаете это снова. За исключением случаев, когда вы не найдете специальных подстрок в S
и они не пусты, в этом случае вы просто добавляете их целиком.
Теперь каждая строка с нечетным индексом в List
является специальной подстрокой. Возможно, вы захотите сослаться на мое упоминание Dictionary
в предыдущей части этого ответа для использования в качестве поиска для добавления Run
из "℠"
, когда найденная подстрока была "(SM)"
.