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     }

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

原文地址:https://www.cnblogs.com/kybs0/p/9688933.html

时间: 2024-12-12 22:24:43

WPF 语言格式化文本控件的相关文章

WCF学习(二)对控件简单了解以及4个文本控件的简介

WPF基础控件 系统默认提供的基础控件: 文本控件介绍与用法 Label控件 label控件:一般用户描述性文字显示. 在Label控件使用时,一般给予用户提示.用法上没有什么很特殊的,label控件的值记住:不是Text 而是 Content属性. TextBlock控件 TextBlock控件,是只读的文本框,无法进行编辑,比较适合显示文本,该文本内容不允许编辑的情况. TextBlock进行设置值的属性是Text 支持直接赋值和数据绑定的方式赋值. TextBox TextBox是支持编辑

WPF利用通过父控件属性来获得绑定数据源RelativeSource

WPF利用通过父控件属性来获得绑定数据源RelativeSource 有时候我们不确定作为数据源的对象叫什么名字,但知道作为绑定源与UI布局有相对的关系,如下是一段XAML代码,说明多层布局控件中放置一个文本控件,来显示父级控件的名称. 1.XAML Html代码 <Grid x:Name="g1" Background="Red" Margin="10"> <DockPanel x:Name="d1" Ba

高质量的基于向量条形码产生机制 WPF Drawing API条形码控件

Barcode Professional for WPF条形码控件是一款轻量级的 .NET 程序集,为你的WPF程序生成高质量的基于矢量的条码,支持大多数流行的一维和二维条形码:Code 39, Code 128, GS1-128, GS1 DataBar (RSS-14),  EAN 13 & UPC, Postal (USPS, British Royal Mail, Australia Post, DHL, etc.), Data Matrix, QR Code, PDF 417, UPS

WPF Step By Step 控件介绍

WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子,希望我们可以对WPF的掌握会更深刻.本文涉及的内容可能较多.请大家慢慢看看.错误之处,还请指出. 本文大纲 1.基本控件介绍与用法. 基本控件介绍与用法 文本控件 Label控件 label控件:一般用户描述性文字显示. 在Label控件使用时,一般给予用户提示.用法上没有什么很特殊的,label

Xceed WPF表单输入控件Xceed Editors for WPF 免费下载及介绍

Xceed Editors for WPF 是一款包含12种功能强大的WPF编辑控件,用户输入控件,每个控件都具有多种风格主题,包含:日期选择控件.复选框.改进的TextBox.数字输入框.值范围输入框等. 具体功能: DatePicker/Calendar:日期选择控件 MaskedTextBox:为输入文本指定一种标记格式 CheckBox:提供了多种风格的复选框,不像传统的WPF复选框 AutoSelectTextBox:当控件具有焦点时内容被选择 ValueRangeTextBox:添加

WPF中的ControlTemplate(控件模板)(转)

原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/28/690993.html WPF中的ControlTemplate(控件模板)                                                                                                                        周银辉 WPF包含数据模板和控件模板,其中控件模板又包括Contro

WPF 使用附加属性增加控件属性

原文:WPF 使用附加属性增加控件属性 使用附加属性增加控件属性,使得这个附加属性在使用的时候没有局限性,可以在任何的控件中使用它来增加所需要的属性,使得控件的属性使用起来非常灵活 一.自定义附加属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

WPF 中动态改变控件模板

在某些项目中,可能需要动态的改变控件的模板,例如软件中可以选择不同的主题,在不同的主题下软件界面.控件的样式都会有所不同,这时即可通过改变控件模板的方式实现期望的功能. 基本方法是当用户点击切换主题按钮是加载新的资源字典,并使用新加载的资源字典替代当前的资源字典这时要用到ResourceManager. 假设现有两个不同的资源字典文件Dictionary1.xaml和Dictionary2.xaml存在于Themes文件夹内: 在MainPage中使用其中一个资源字典作为默认样式文件: <Win

MFC小程序003------MFC使用WebBrowser组件,在对话框中创建滚动视图,动态创建一个静态文本控件并设置鼠标单击的消息响应

MFC小程序截图: 一.在MFC中简单使用WebBrowser的ActiveX插件的方法: 见博文:  http://blog.csdn.net/supermanking/article/details/5866213 二.在对话框中创建视图(我这里创建的是一个滚动视图): 见博文: http://blog.csdn.net/clever101/article/details/4873994 http://blog.csdn.net/clever101/article/details/37790