Как вставить авторское право, товарный знак, знак обслуживания и т. д. в текстовое поле WPF, когда шрифт не поддерживает символы

у нас есть приложение WPF, которое отображает текст, содержащий различные корпоративные символы; такие как товарный знак, зарегистрированный товарный знак, авторское право и знак обслуживания.

в базе данных есть несколько полей, которые включают стандартные корпоративные символы. Первоначально данные были отмечены следующим образом:

Example Corp(TM) or Example Plan (SM)

мы можем легко изменить заполнители на их соответствующие эквиваленты Unicode; и на самом деле в большинстве случаев.

проблема у нас является ли шрифт, используемый приложением, не поддерживает символ знака обслуживания (который является просто надписанным SM). Скорее всего, мы не можем заменить шрифт или изменить его.

поля могут быть простым именем продукта с символом в конце или длинным описанием с символом, содержащимся 0 или более раз. Мы привязываем текстовые поля или метки непосредственно к ViewModel и / или бизнес-объекту (обычно через DataTemplates). Все данные в приложении только для чтения.

Итак, предполагая, что мы должны решать это с помощью кода (в C# и WPF), каковы мои варианты?

3 ответов


Edit: я обнаружил в другом ответе, что TextBlock также Inlines коллекция, к которой можно добавить Runs. Anvaka это гениально использует вложенное свойство в качестве своего рода конвертера.


у меня была пара идей о том, как подойти к этому. Только один будет обрабатывать перенос слов правильно и обрабатывать символы с разными шрифтами.

использовать FlowDocumentScrollViewer и привязать строку к нему с помощью ValueConverter, который преобразует строку FlowDocument.

<FlowDocumentScrollViewer
    HorizontalScrollBarVisibility="Hidden"
    VerticalScrollBarVisibility="Hidden"
    Document="{Binding MyString, Converter={StaticResource MyConverter}}" />

вы можете создать свойства на конвертере, чтобы установить обычные свойства шрифта, которые не могут быть установлены на FlowDocumentScrollViewer и должен быть установлен на FlowDocument конвертер создает. Вероятно, вам также понадобятся некоторые свойства шрифта для подстрок исключений, которым нужен другой шрифт (и, возможно, другой размер). Другой вариант-создать 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() нашел ли он подстроку или нет. Зацикливаясь на известных специальных подстроках, вы можете найти первый экземпляр любого из них с помощью сравнения индексов, также отложив длину подстроки.

каждый раз, когда вы находите самую раннюю специальную подстроку в string S (если есть), вы делаете производные строки A, B и C. B специальные подстроки, A и C несколько до и после. Добавить A и B до List и C становится S и вы делаете это снова. За исключением случаев, когда вы не найдете специальных подстрок в S и он не пуст, и в этом случае вы просто добавляете его целиком.

теперь каждая нечетная индексированная строка в List специальные подстроки. Вы можете сослаться на мое упоминание о Dictionary в предыдущей части этого ответа для использования в качестве поиска для добавления Run of "℠" когда подстрока вас нашел "(SM)".


Если ваш элемент отображения поддерживает несколько шрифтов, таких как элемент управления RichTextbox, вы можете отформатировать строку с соответствующими шрифтами вокруг символов (TM) и (SM).


несколько уродливый способ сделать это, но один из вариантов может заключаться в размещении небольших изображений, содержащих предварительно отображенный символ в соответствующих местах. Поскольку данные не статичны (если я правильно понимаю), вам нужно будет вычислить положение для изображений динамически, что будет сложно, если шрифт не будет фиксированной ширины.