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

时间:2010-01-28 17:31:55

标签: c# wpf textbox symbols

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

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

Example Corp(TM) or Example Plan (SM)

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

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

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

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

3 个答案:

答案 0 :(得分:4)

修改:我在另一个答案中发现,TextBlock还有一个Inlines集合,可以添加Run个。 Anvaka's answer巧妙地使用附属属性作为一种转换器。


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

使用FlowDocumentScrollViewer并使用ValueConverter将字符串绑定到该字符串,将字符串转换为FlowDocument

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

您可以在转换器上创建属性以设置常规字体属性,这些属性无法在FlowDocumentScrollViewer上设置,必须在转换器创建的FlowDocument上设置。对于需要不同Font(可能还有不同大小)的异常子字符串,您可能还需要一些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 );

使用不同的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(如果有)中找到最早的特殊子字符串时,您就会生成派生字符串ABCB是特殊的子字符串,AC是之前和之后。将AB附加到ListC成为新S,然后重新执行此操作。除非您在S中找不到特殊的子字符串且它不是空的,在这种情况下,您只需将其全部附加。

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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