Как вставить авторское право, товарный знак, знак обслуживания и т. Д. В текстовое поле WPF, если шрифт не поддерживает символы
У нас есть приложение WPF, которое отображает текст, содержащий различные корпоративные символы; такие как товарный знак, зарегистрированный товарный знак, авторское право и знак обслуживания.
В базе данных есть несколько полей, которые включают стандартные корпоративные символы. Первоначально данные были помечены следующим образом:
Example Corp(TM) or Example Plan (SM)
Мы можем легко изменить заполнители на их соответствующие эквиваленты Unicode; и на самом деле есть в большинстве случаев.
Проблема, которую мы имеем, состоит в том, что шрифт, используемый приложением, не поддерживает символ Service Mark (который является просто надстрочным символом SM). Скорее всего, мы не сможем заменить шрифт или отредактировать его.
Поля могут быть простым названием продукта с символом в конце или длинным описанием с символом, содержащим 0 или более раз. Мы привязываем TextBoxes или Labels непосредственно к ViewModel и / или бизнес-объекту (обычно через DataTemplates). Все данные в приложении доступны только для чтения.
Итак, предположим, что мы должны решить эту проблему с помощью кода (в C# и WPF), каковы мои варианты?
3 ответа
Изменить: я обнаружил в другом ответе, что TextBlock
также имеет Inlines
коллекция, в которую можно добавить Run
s. Ответ Анваки изобретательно использует прикрепленное свойство как своего рода конвертер.
У меня была пара идей о том, как подойти к этому. Только один мог бы правильно обрабатывать перенос слов и обрабатывать символы разными шрифтами.
Использовать FlowDocumentScrollViewer
и привязать строку к нему с помощью ValueConverter
который преобразует строку в FlowDocument
,
<FlowDocumentScrollViewer
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Document="{Binding MyString, Converter={StaticResource MyConverter}}" />
Вы можете создать свойства в конвертере, чтобы установить обычные свойства шрифта, которые не могут быть установлены на FlowDocumentScrollViewer
и должен быть установлен на FlowDocument
что конвертер создает. Возможно, вам также понадобятся некоторые свойства Font для подстрок исключений, которым нужен другой шрифт (и, возможно, другой размер). Другой вариант заключается в создании Binding
на 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)"
,
Если ваш элемент отображения поддерживает несколько шрифтов, например элемент управления RichTextbox, вы можете отформатировать строку с соответствующими шрифтами вокруг символов (TM) и (SM).
Несколько уродливый способ сделать это, но одним из вариантов может быть размещение небольших изображений, содержащих предварительно визуализированный символ, в соответствующих местах. Поскольку данные не являются статичными (если я правильно понимаю), вам необходимо динамически рассчитывать положение изображений, что будет сложно, если шрифт не имеет фиксированной ширины.