Как вставить авторское право, товарный знак, знак обслуживания и т. Д. В текстовое поле WPF, если шрифт не поддерживает символы - PullRequest
6 голосов
/ 28 января 2010

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

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

Example Corp(TM) or Example Plan (SM)

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 29 января 2010

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)".

1 голос
/ 28 января 2010

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

0 голосов
/ 06 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...