WPF 語言格式化文本控件

前言

本章講述正確添加語言資源的方式,以及一段語言資源的多種樣式顯示。html

例如:「@Winter,你好!感謝已使用軟件 800 天!git

 

在添加如上多語言資源項時,「XX,你好!感謝已使用軟件 X 天!」github

那麼,你是怎麼添加語言資源的呢?web

分別添加,「,你好!」、「感謝已使用軟件」、「年」3個,再經過界面綁定動態變量 暱稱和使用天數post

假如你是按照如上添加語言資源的,那麼問題來了,添加如上英文語言資源呢?是否是也分別添加單個資源,再拼湊綁定?學習

添加語言資源

正確的作法是,添加整個語言資源,{0},你好!感謝已使用軟件 {1} 天!url

緣由:使用格式化的語言資源,那麼將中文資源翻譯成英文或者其它語言後,獲得的譯文才符合原有的含義。spa

否則,一段一段翻譯後的文本拼接,獲得的只會是,中式英文之類的。。。翻譯

語言格式化控件

在添加了語言資源後,如何在WPF界面顯示呢?code

簡單的文本樣式

假如只是實現簡單的文本拼接,且樣式相同時,能夠直接綁定動態變量值 - 暱稱和使用年限,而後經過StringFormat或者Conveter去處理格式化文本。

  • 若是隻有一個動態變量,直接使用StringFormat處理便可。Text="{Binding Name,StringFormat={StaticResource TheFormatedText}}"
  • 若是多個動態變量,能夠使用多重綁定+Converter,實現文本格式化。

詳細可查看 WPF StringFormat 格式化文本

複雜的文本樣式

假如格式化文本,須要實現複雜的樣式和操做,例如:

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

詳細代碼實現,可查看Github源碼Demo

相關文章
相關標籤/搜索