我们有一个WPF应用程序,显示包含各种公司符号的文本;如商标,注册商标,版权和服务商标。
数据库包含一些包含标准公司符号的字段。最初,数据标记如下:
Example Corp(TM) or Example Plan (SM)
我们可以轻松地将占位符更改为各自的Unicode等价物;实际上在大多数情况下都有。
我们遇到的问题是应用程序使用的字体不支持服务标记符号(它只是一个上标 SM )。有可能我们无法替换字体或编辑它。
字段可以是带有符号末尾的简单产品名称,也可以是带有0次或更多次符号的长描述。我们将TextBoxes或Labels直接绑定到ViewModel和/或业务对象(通常通过DataTemplates)。应用程序中的所有数据都是只读的。
所以,假设我们必须通过代码解决这个问题(在C#和WPF中),我的选择是什么?
答案 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
(如果有)中找到最早的特殊子字符串时,您就会生成派生字符串A
,B
和C
。 B
是特殊的子字符串,A
和C
是之前和之后。将A
和B
附加到List
,C
成为新S
,然后重新执行此操作。除非您在S
中找不到特殊的子字符串且它不是空的,在这种情况下,您只需将其全部附加。
现在List
中的每个奇数索引字符串都是一个特殊的子字符串。您可能希望在我的答案的前一部分中提及Dictionary
,以便在您找到的子字符串{{1}时用作查找以添加Run
"℠"
}}
答案 1 :(得分:1)
如果您的显示元素支持多种字体(如RichTextbox控件),则可以使用(TM)和(SM)符号周围的相应字体格式化字符串。
答案 2 :(得分:0)
一种有点丑陋的方法,但一种选择可能是将包含预渲染符号的小图像放在适当的位置。由于数据不是静态的(如果我理解正确的话),你需要动态计算图像的位置,除非字体是固定宽度的,否则很难。