如果字体不支持符号,如何在WPF文本框中插入版权,商标,服务标记等
我们有一个WPF应用程序,显示包含各种公司符号的文本; 如商标,注册商标,版权和服务标志。
数据库包含一些包含标准公司符号的字段。 最初,数据标记如下:
Example Corp(TM) or Example Plan (SM)
我们可以轻松地将占位符更改为各自的Unicode等价物; 实际上在大多数情况下都有。
我们遇到的问题是应用程序使用的字体不支持服务标记符号(它只是一个上标的SM )。 有可能我们无法替换字体或编辑它。
字段可以是带有符号末尾的简单产品名称,也可以是带有0次或更多次符号的长描述。 我们将TextBoxes或Labels直接绑定到ViewModel和/或业务对象(通常通过DataTemplates)。 应用程序中的所有数据都是只读的。
所以,假设我们必须通过代码解决这个问题(在C#和WPF中),我的选择是什么?
编辑:我在一个不同的答案中发现, TextBlock
还有一个可以添加Run
的Inlines
集合。 Anvaka的答案巧妙地使用附属物作为一种转换器。
关于如何处理这个问题我有几个想法。 只有一个会正确处理自动换行并处理不同字体的字符运行。
使用FlowDocumentScrollViewer
并使用将字符串转换为FlowDocument
的ValueConverter
将字符串绑定到该字符串。
您可以在转换器上创建属性以设置常规字体属性,这些属性不能在FlowDocumentScrollViewer
上设置,必须在转换器创建的FlowDocument
上设置。 对于需要不同Font(可能还有不同大小)的exception子串,您可能还需要一些Font属性。 另一种选择是在FlowDocument
为其中一些属性( RelativeSource
)创建Binding
。
以下是在代码中创建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 );
使用不同的Font向段落添加特殊子字符串:
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
,以便在您找到的子字符串为"(SM)"
时用作添加"℠"
Run
的查找。
如果您的显示元素支持多种字体(如RichTextbox控件),则可以使用(TM)和(SM)符号周围的相应字体格式化字符串。
这是一种有点难看的方法,但一种选择可能是将包含预渲染符号的小图像放在适当的位置。 由于数据不是静态的(如果我理解正确的话),你需要动态地计算图像的位置,除非字体是固定宽度的,否则这将是困难的。