WPF 语言格式化文本控件

简介: 原文:WPF 语言格式化文本控件前言 本章讲述正确添加语言资源的方式,以及一段语言资源的多种样式显示。 例如:“@Winter,你好!感谢已使用软件 800 天!”   在添加如上多语言资源项时,“XX,你好!感谢已使用软件 X 天!” 那么,你是怎么添加语言资源的呢? 分别添加,“,...
原文: WPF 语言格式化文本控件

前言

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

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

 

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

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

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

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

添加语言资源

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

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

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

语言格式化控件

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

简单的文本样式

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

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

复杂的文本样式

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

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

以上,如何处理?

语言格式化控件实现

Demo显示效果:

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

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

2. 重写文本依赖属性

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

 1     public new static DependencyProperty TextProperty =
 2         DependencyProperty.Register("Text", typeof(string), typeof(ComplexTextBlock), new PropertyMetadata(TextPropertyChanged));
 3 
 4     public static string GetText(DependencyObject element)
 5     {
 6         return (string)element.GetValue(TextProperty);
 7     }
 8     public static void SetText(DependencyObject element, string value)
 9     {
10         element.SetValue(TextProperty, value);
11     }
12 
13     private static void TextPropertyChanged(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     public ContentFormatsCollection ContentFormats
 9     {
10         get => (ContentFormatsCollection)GetValue(ContentFormatsProperty);
11         set => SetValue(ContentFormatsProperty, value);
12     }
13 
14     private static void ContentFormatsPropertyChanged(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 void LoadComplexContent(DependencyObject dependencyObject)
  8     {
  9         if (!(dependencyObject is ComplexTextBlock 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 = new StackPanel();
 33         stackPanel.Orientation = Orientation.Horizontal;
 34         stackPanel.VerticalAlignment = VerticalAlignment.Center;
 35 
 36         int formatIndex = 0;
 37         foreach (var paraText in list)
 38         {
 39             if (paraText == FormattedKey)
 40             {
 41                 stackPanel.Children.Add(contentFormats[formatIndex++]);
 42             }
 43             else
 44             {
 45                 var textLine = new TextBlock();
 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(string text)
 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             return list;
 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         return list;
103     }

5. 控件的使用

界面显示:

调用实现:

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 LinkedTextBlock}" VerticalAlignment="Center"/>
6             </local:ContentFormatsCollection>
7         </local:ComplexTextBlock.ContentFormats>
8     </local:ComplexTextBlock>

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

 

目录
相关文章
|
7月前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
408 0
|
7月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
156 1
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
622 0
|
4月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
4月前
|
C# 开发者 Windows
一款基于Fluent设计风格、现代化的WPF UI控件库
一款基于Fluent设计风格、现代化的WPF UI控件库
123 1
|
4月前
|
C# Windows
WPF中如何使用HandyCotrol控件库
WPF中如何使用HandyCotrol控件库
218 1
|
4月前
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
158 0
|
4月前
|
C# UED 定位技术
WPF控件大全:初学者必读,掌握控件使用技巧,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,控件是实现用户界面交互的关键元素。WPF提供了丰富的控件库,包括基础控件(如`Button`、`TextBox`)、布局控件(如`StackPanel`、`Grid`)、数据绑定控件(如`ListBox`、`DataGrid`)等。本文将介绍这些控件的基本分类及使用技巧,并通过示例代码展示如何在项目中应用。合理选择控件并利用布局控件和数据绑定功能,可以提升用户体验和程序性能。
93 0
|
4月前
|
开发框架 前端开发 JavaScript
WPF应用开发之控件动态内容展示
WPF应用开发之控件动态内容展示
|
4月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件