如果字体不支持符号,如何在WPF文本框中插入版权,商标,服务标记等

我们有一个WPF应用程序,显示包含各种公司符号的文本; 如商标,注册商标,版权和服务标志。

数据库包含一些包含标准公司符号的字段。 最初,数据标记如下:

Example Corp(TM) or Example Plan (SM)

我们可以轻松地将占位符更改为各自的Unicode等价物; 实际上在大多数情况下都有。

我们遇到的问题是应用程序使用的字体不支持服务标记符号(它只是一个上标的SM )。 有可能我们无法替换字体或编辑它。

字段可以是带有符号末尾的简单产品名称,也可以是带有0次或更多次符号的长描述。 我们将TextBoxes或Labels直接绑定到ViewModel和/或业务对象(通常通过DataTemplates)。 应用程序中的所有数据都是只读的。

所以,假设我们必须通过代码解决这个问题(在C#和WPF中),我的选择是什么?

编辑:我在一个不同的答案中发现, TextBlock还有一个可以添加RunInlines集合。 Anvaka的答案巧妙地使用附属物作为一种转换器。


关于如何处理这个问题我有几个想法。 只有一个会正确处理自动换行并处理不同字体的字符运行。

使用FlowDocumentScrollViewer并使用将字符串转换为FlowDocumentValueConverter将字符串绑定到该字符串。

  

您可以在转换器上创建属性以设置常规字体属性,这些属性不能在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 (如果有)中找到最早的特殊子字符串时,都会生成派生字符串ABC B是特殊子串, AC是前后。 将AB附加到ListC成为新的S ,然后再次执行。 除非你在S找不到特殊的子串并且它不是空的,在这种情况下你只需要将它全部附加。

现在List中的每个奇数索引字符串都是一个特殊的子字符串。 您可能希望在本答案的前一部分中引用我提到的Dictionary ,以便在您找到的子字符串为"(SM)"时用作添加"℠" Run的查找。

如果您的显示元素支持多种字体(如RichTextbox控件),则可以使用(TM)和(SM)符号周围的相应字体格式化字符串。

这是一种有点难看的方法,但一种选择可能是将包含预渲染符号的小图像放在适当的位置。 由于数据不是静态的(如果我理解正确的话),你需要动态地计算图像的位置,除非字体是固定宽度的,否则这将是困难的。