WPF 語言格式化文本控制項

来源:https://www.cnblogs.com/kybs0/archive/2018/09/21/9688933.html
-Advertisement-
Play Games

前言 本章講述正確添加語言資源的方式,以及一段語言資源的多種樣式顯示。 例如:“@Winter,你好!感謝已使用軟體 800 天!” 在添加如上多語言資源項時,“XX,你好!感謝已使用軟體 X 天!” 那麼,你是怎麼添加語言資源的呢? 分別添加,“,你好!”、“感謝已使用軟體”、“年”3個,再通過界 ...


前言

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

例如:“@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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題意 題目鏈接 Sol 如果給出的樹是鏈的話顯然就是LIS 不是鏈的時候直接當鏈做,每個節點維護一個multiset表示計算LIS過程中的單調棧 啟髮式合併即可 時間複雜度:$O(nlog^2n)$ ...
  • 明白生產環境中的jvm參數 寫代碼的時候,程式寫完了,發到線上去運行,跑一段時間後,程式變慢了,cpu負載高了……一堆問題出來了,所以瞭解一下生產環境的機器上的jvm配置是有必要的。比如說: JDK版本是多少?採用何種垃圾回收器? 程式啟動的時候預設分配堆記憶體空間是多少?隨著程式的運行,程式最多能使 ...
  • 每個程式員、或者說每個工作者都應該有自己的職業規劃,如果你不是富二代,不是官二代,也沒有職業規劃,希望你可以思考一下自己的將來。今天給大家分享的是一篇來自阿裡Java架構師對普通程式員的職業建議,希望對你有啟發。 普通程式員,三年成為年薪70w架構師,只因做到了這些 ...
  • 1.分析 上傳文件的過程:客服端選擇一個文件後,寫入到伺服器端,伺服器端使用一個目錄來存儲該文件--底層IO流操作 2.jsp文件上的表單設計 表單傳輸格式用multipart/form-data,要上傳的文件input標簽name屬性最好用同樣的首碼或者尾碼好獲取 3後臺Servlet處理 1.S ...
  • 題意 題目鏈接 題意:給出一張無向圖,每次詢問兩點之間的最短路,滿足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道題。 首先建出一個dfs樹。 因為邊數-點數非常少,所以我們可以對於某些非樹邊特殊考慮。 具體做法是:對於非樹邊連接的兩個點,暴力求出 ...
  • 分散式架構有以下幾點普適性的共性需求: 1. 提供集群的集中化的配置管理功能,可以不重啟就讓新的配置參數生效,類似與配置中心 2. 簡單可靠的集群節點動態發現機制,便於動態發現服務,動態擴展節點 3. 簡單可靠的leader選舉機制 4. 提供分散式鎖 zookeeper的數據結構整體上可以看作一顆 ...
  • 在前面大致預覽了常用變數的結構之後,我們今天來仔細的剖析一下字元串的具體實現。 一、字元串的結構 zend_refcounted_h對應的結構體: 下麵我們來瞭解一下具體每個成員的作用: gc:就是_zend_refcounted_h結構體,主要作用是引用計數以及標記變數的類別。 h:字元串的哈希值 ...
  • 前言 並行編程:通過編碼方式利用多核或多處理器稱為並行編程,多線程概念的一個子集。 並行處理:把正在執行的大量的任務分割成小塊,分配給多個同時運行的線程。多線程的一種。 並行編程分為如下幾個結構: 1.並行的LINQ或PLINQ 2.Parallel類 3.任務並行結構 4.併發集合 5.SpinL ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...