WPF 语言格式化文本控件

摘要:
语言格式化控件在添加了语言资源后,如何在WPF界面显示呢?详细可查看WPFStringFormat格式化文本复杂的文本样式假如格式化文本,需要实现复杂的样式和操作,例如:文本+按钮文本+超链接加粗文本+普通文本+红色文本以上,如何处理?1publicstaticDependencyPropertyContentFormatsProperty=2DependencyProperty.Register;45///6///格式化内容列表7///8publicContentFormatsCollectionContentFormats9{10get=˃GetValue;11set=˃SetValue;12}1314privatestaticvoidContentFormatsPropertyChanged15{16LoadComplexContent;17}4.处理格式化文本处理方法,主要是将当前格式化的文本拆分为多个文本段落和格式化字符“{0}”,然后将待显示的动态变量替换拆分后列表中的格式化字符。
前言

本章讲述正确添加语言资源的方式,以及一段语言资源的多种样式显示。

例如:“@Winter,你好!感谢已使用软件 800 天!

在添加如上多语言资源项时,“XX,你好!感谢已使用软件 X 天!”

那么,你是怎么添加语言资源的呢?

分别添加,“,你好!”、“感谢已使用软件”、“年”3个,再通过界面绑定动态变量 昵称和使用天数

假如你是按照如上添加语言资源的,那么问题来了,添加如上英文语言资源呢?是不是也分别添加单个资源,再拼凑绑定?

添加语言资源

正确的做法是,添加整个语言资源,{0},你好!感谢已使用软件 {1} 天!

原因:使用格式化的语言资源,那么将中文资源翻译成英文或者其它语言后,得到的译文才符合原有的含义。

不然,一段一段翻译后的文本拼接,得到的只会是,中式英文之类的。。。

语言格式化控件

在添加了语言资源后,如何在WPF界面显示呢?

简单的文本样式

假如只是实现简单的文本拼接,且样式相同时,可以直接绑定动态变量值 - 昵称和使用年限,然后通过StringFormat或者Conveter去处理格式化文本。

  • 如果只有一个动态变量,直接使用StringFormat处理即可。Text="{Binding Name,StringFormat={StaticResource TheFormatedText}}"
  • 如果多个动态变量,可以使用多重绑定+Converter,实现文本格式化。

详细可查看 WPF StringFormat 格式化文本

复杂的文本样式

假如格式化文本,需要实现复杂的样式和操作,例如:

  1. 文本+按钮
  2. 文本+超链接
  3. 加粗文本+普通文本+红色文本

以上,如何处理?

语言格式化控件实现

Demo显示效果:

WPF 语言格式化文本控件第1张

1. 添加一个继承TextBlock的用户控件ComplexTextBlock

1     /// <summary>
2     ///解决复杂文本格式化样式的文本框控件
3     ///如"已使用软件 {0} 天",天数需要标红加粗,或者用于【文本】【文字按钮】【文本】的组合
4     /// </summary>
5     public classComplexTextBlock : TextBlock
6 {
7 
8     }

2. 重写文本依赖属性

为了监听文本变更,所以重写文本的依赖属性。文本变更事件处理,之后会详细介绍~

1     public new static DependencyProperty TextProperty =
2         DependencyProperty.Register("Text", typeof(string), typeof(ComplexTextBlock), newPropertyMetadata(TextPropertyChanged));
3 
4     public static stringGetText(DependencyObject element)
5 {
6         return (string)element.GetValue(TextProperty);
7 }
8     public static void SetText(DependencyObject element, stringvalue)
9 {
10 element.SetValue(TextProperty, value);
11 }
12 
13     private static voidTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
14 {
15 LoadComplexContent(d);
16     }

3. 添加动态变量显示的控件列表

如“@Winter,你好!感谢已使用软件 800 天,可查看详情!”,可以将昵称、使用时间、详情,分别设置为文本控件、文本控件、超链接按钮,然后添加到动态控件列表中。

1     public static DependencyProperty ContentFormatsProperty =
2         DependencyProperty.Register("ContentFormats", typeof(ContentFormatsCollection), typeof(ComplexTextBlock),
3             new PropertyMetadata(default(ContentFormatsCollection), ContentFormatsPropertyChanged));
4 
5     /// <summary>
6     ///格式化内容列表
7     /// </summary>
8     publicContentFormatsCollection ContentFormats
9 {
10         get =>(ContentFormatsCollection)GetValue(ContentFormatsProperty);
11         set =>SetValue(ContentFormatsProperty, value);
12 }
13 
14     private static voidContentFormatsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
15 {
16 LoadComplexContent(d);
17     }

4. 处理格式化文本

处理方法,主要是将当前格式化的文本拆分为多个文本段落和格式化字符“{0}”,然后将待显示的动态变量(文本控件/按钮等)替换拆分后列表中的格式化字符。组合成完整的显示文本。

其中,需要注意的是,文本的样式继承。

1     private const string FormattedKey = "{0}";
2 
3     /// <summary>
4     ///加载复杂文本
5     /// </summary>
6     /// <param name="dependencyObject"></param>
7     private static voidLoadComplexContent(DependencyObject dependencyObject)
8 {
9         if (!(dependencyObject isComplexTextBlock complexTextBlock))
10 {
11             return;
12 }
13 
14         string text =GetText(complexTextBlock);
15         var contentFormats =complexTextBlock.ContentFormats;
16 
17         if (string.IsNullOrEmpty(text) || contentFormats == null || contentFormats.Count == 0)
18 {
19             return;
20 }
21 
22         for (int i = 0; i < contentFormats.Count; i++)
23 {
24             text = text.Replace(i.ToString(), "0");
25 }
26 
27         var list =GetTextList(text);
28 
29         //清空当前文本
30         complexTextBlock.Text = null;
31         //分段加载文本
32         var stackPanel = newStackPanel();
33         stackPanel.Orientation =Orientation.Horizontal;
34         stackPanel.VerticalAlignment =VerticalAlignment.Center;
35 
36         int formatIndex = 0;
37         foreach (var paraText inlist)
38 {
39             if (paraText ==FormattedKey)
40 {
41                 stackPanel.Children.Add(contentFormats[formatIndex++]);
42 }
43             else
44 {
45                 var textLine = newTextBlock();
46                 if (complexTextBlock.Style != null)
47 {
48                     textLine.Style =complexTextBlock.Style;
49 }
50                 else
51 {
52                     textLine.VerticalAlignment =complexTextBlock.VerticalAlignment;
53                     textLine.HorizontalAlignment =complexTextBlock.HorizontalAlignment;
54                     textLine.Background =complexTextBlock.Background;
55                     textLine.FontFamily =complexTextBlock.FontFamily;
56                     textLine.FontSize =complexTextBlock.FontSize;
57                     textLine.Foreground =complexTextBlock.Foreground;
58                     textLine.FontWeight =complexTextBlock.FontWeight;
59                     textLine.FontStyle =complexTextBlock.FontStyle;
60 }
61                 textLine.Text =paraText;
62 stackPanel.Children.Add(textLine);
63 }
64 }
65 complexTextBlock.Inlines.Add(stackPanel);
66 }
67 
68     /// <summary>
69     ///获取分段文本列表
70     /// </summary>
71     /// <param name="text"></param>
72     /// <returns></returns>
73     private static List<string> GetTextList(stringtext)
74 {
75         var list = new List<string>();
76         var formatIndex =text.IndexOf(FormattedKey, StringComparison.Ordinal);
77 
78         //1.不存在格式化关键字,则直接返回当前文本
79         if (formatIndex == -1)
80 {
81 list.Add(text);
82             returnlist;
83 }
84 
85         //2.存在格式化关键字
86         if (formatIndex == 0)
87 {
88 list.Add(FormattedKey);
89 }
90         else
91 {
92             list.Add(text.Substring(0, formatIndex));
93 list.Add(FormattedKey);
94 }
95 
96         //获取下一格式化文本
97         if (formatIndex <text.Length)
98 {
99             list.AddRange(GetTextList(text.Substring(formatIndex +FormattedKey.Length)));
100 }
101 
102         returnlist;
103     }

5. 控件的使用

界面显示:

WPF 语言格式化文本控件第2张

调用实现:

1     <local:ComplexTextBlock Text="小王,好好{0},详见{1}!"Style="{StaticResource ComplexTextBlockStyle}"Margin="0 10 0 0">
2         <local:ComplexTextBlock.ContentFormats>
3             <local:ContentFormatsCollection>
4                 <Button Content="学习"Click="ButtonBase_OnClick"VerticalAlignment="Center"></Button>
5                 <Button x:Name="LinkedButton"Content="学习计划"Click="LinkedButton_OnClick"Style="{StaticResource LinkeButton}"VerticalAlignment="Center"/>
6             </local:ContentFormatsCollection>
7         </local:ComplexTextBlock.ContentFormats>
8     </local:ComplexTextBlock>

详细代码实现,可查看Github源码Demo

免责声明:文章转载自《WPF 语言格式化文本控件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇yum 彻底删除nodejs,重新安装12月1号 MacOS系统命令行操作方式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WPF 自定义滚动条(ScrollView、ScrollBar)样式【转载】

一、滚动条基本样式 本次修改Scrollview及ScrollBar滚动条样式是通过纯样式实现的。修改的内容包含滚动条的颜色,上下按钮的隐藏。另外添加了鼠标经过滚动条动画。 style样式如下: <!-- ScrollViewer 滚动条 --> <Style x:Key="ScrollBarThumb" TargetType="...

WPF界面开发:DevExpress WPF在GridControl中固定行时处理时刻

DevExpress广泛应用于ECM企业内容管理、 成本管控、进程监督、生产调度,在企业/政务信息化管理中占据一席重要之地。通过DevExpress WPF Controls,您能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件的衍伸产品,还是以数据为中心的商业智能...

[WPF] 跨线程控制窗体UI

呼叫线程无法存取此对象 在WPF、WinForm这些应用程序中,必需是UI线程才能控制窗体。如果像是下列的范例程序一样,使用了非UI线程来控制窗体,那就会看到内容为「呼叫线程无法存取此对象,因为此对象属于另外一个线程」的InvalidOperationException例外错误。 <Window x: xmlns="http://...

WPF在圆上画出刻度线

思路 我们可以使用Ellipse先画出一个圆当背景,然后用Canvas再叠加画上刻度线,就能得到如下的效果 我们先用Ellipse画一个橙色的圆,然后将Canvas的宽度和高度绑定到Ellipse的宽度和高度 <Grid> <Ellipse Fill="Orange" Width="400" Height="400" N...

贫民窟里的WPF系列讲座(一)

最近讲了一套完整的WPF课程,感觉教学效果还很不错。我准备给MSDN录15期左右的事情,这几篇文章是配合视频一起来看的。我相信大家都是很喜欢研究新技术的,但是研究新技术的时候会遇到很多困难,譬如书籍的选择,工具的选择,环境的配置等等很多很多问题。 这里我结合自己学习的历程,分享一下。这里我说一下我当时学习的硬件条件,由于我的笔记本是IBM的T40,CPU是...

如何将WPF browser app 转换成WPF windows application

转载于:http://dotnetframework.blogspot.com.au/2011/01/wpf-browser-application-wpf-windows.html WPF Browser Application 是WPF 中较新的功能。其实它的基本概念,仍然是ClickOnce Application。所以在权限及安控的处理上,必须很小...