WPF 语言格式化文本控件

前言 本章讲述正确添加语言资源的方式,以及一段语言资源的多种样式显示。 例如:“@Winter,你好!感谢已使用软件 800 天!” 在添加如上多语言资源项时,“XX,你好!感谢已使用软件 X 天!” 那么,你是怎么添加语言资源的呢? 分别添加,“,你好!”、“感谢已使用软件”、“年”3个,再通过界面绑定动态变量 昵称和使用天数? 假如你是按照如上添加语言资源的,那么问题来了,添加如上英文语言资源呢?是不是也分别添加单个资源,再拼凑绑定? 添加语言资源 正确的做法是,添加整个语言资源,“{0},你好!感谢已使用软件 {1} 天!” 原因:使用格式化的语言资源,那么将中文资源翻译成英文或者其它语言后,得到的译文才符合原有的含义。 不然,一段一段翻译后的文本拼接,得到的只会是,中式英文之类的。。。 语言格式化控件 在添加了语言资源后,如何在WPF界面显示呢? 简单的文本样式 假如只是实现简单的文本拼接,且样式相同时,可以直接绑定动态变量值 - 昵称和使用年限,然后通过StringFormat或者Conveter去处理格式化文本。 如果只有一个动态变量,直接使用StringFormat处理即可。Text="{Binding Name,StringFormat={StaticResource TheFormatedText}}" 如果多个动态变量,可以使用多重绑定+Converter,实现文本格式化。 复杂的文本样式 假如格式化文本,需要实现复杂的样式和操作,例如: 文本+按钮 文本+超链接 加粗文本+普通文本+红色文本 以上,如何处理? 语言格式化控件实现 Demo显示效果: 1. 添加一个继承TextBlock的用户控件ComplexTextBlock 复制代码 1 /// 2 /// 解决复杂文本格式化样式的文本框控件 3 /// 如"已使用软件 {0} 天",天数需要标红加粗,或者用于【文本】【文字按钮】【文本】的组合 4 /// 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 /// 6 /// 格式化内容列表 7 /// 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 /// 4 /// 加载复杂文本 5 /// 6 /// 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 /// 69 /// 获取分段文本列表 70 /// 71 /// 72 /// 73 private static List GetTextList(string text) 74 { 75 var list = new List(); 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 2 3 4 5
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信