WPF應用 - 實現可上下標的文本框

System.Windows.Controls.RichTextBox

首先考慮使用這個控件

上下標設置

var textrange = new TextRange(rtb.Selection.Start, rtb.Selection.End);
textrange.ApplyPropertyValue(Run.BaselineAlignmentProperty, BaselineAlignment.Superscript); //上標
textrange.ApplyPropertyValue(Run.BaselineAlignmentProperty, BaselineAlignment.Subscript); //下標

上下標的設置沒有問題,顯示也沒有問題,但當把RichTextBox中的內容存取時,問題出現了:
1. 保存的rtf格式中上下標信息丟失;
2. 對RichTextBox的文本信息進行右鍵複製,粘貼到word中,上下標信息丟失

相關代碼如下:

    public static class Extend
    {
        public static string GetText(this RichTextBox rtb, string dataformat)
        {
            if (null == rtb)
                return "";

            var range = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
            using (var ms = new MemoryStream())
            {
                range.Save(ms, dataformat);
                ms.Seek(0, SeekOrigin.Begin);
                using (var sr = new StreamReader(ms))
                    return sr.ReadToEnd();
            }
        }

        public static void SetText(this RichTextBox rtb, string text, string dataformat)
        {
            if (null == rtb || null == text)
                return;
            var range = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(text)))
            {
                range.Load(ms, dataformat);
            }
        }
    }

保存rtf格式上下標信息丟失

dataformat傳遞的是DataFormats.Rtf。網上搜尋答案,以另外一種格式存取沒有問題,即傳遞dataformat爲DataFormats.Xaml

Copy to Word上下標信息丟失

找到了另外一種設置上下標的方式,即Typography.Variants
在WPF中設置該屬性,顯示如下:
這裏寫圖片描述
Copy To Word後顯示:
這裏寫圖片描述
顯示的結果與使用BaselineAlignment的結果正好相反。Good! 找到解決方案了,Wpf上顯示的時候使用BaseLineAlignment,而在後臺保存時使用Typography.Variants

代碼如下

    public static class TextRangeExtend
    {
        public static string GetText(this TextRange tr, string dataformat)
        {
            if (null == tr)
                return "";
            using (var ms = new MemoryStream())
            {
                tr.Save(ms, dataformat);
                ms.Seek(0, SeekOrigin.Begin);
                using (var sr = new StreamReader(ms))
                    return sr.ReadToEnd();
            }
        }

        public static void SetText(this TextRange tr, string val, string dataformat)
        {
            if (null == tr)
                return;
            if (string.IsNullOrEmpty(val))
            {
                tr.Text = "";
                return;
            }

            using (var ms = new MemoryStream(Encoding.Default.GetBytes(val)))
            {
                tr.Load(ms, dataformat);
            }
        }

        public static string GetTextRtf(this TextRange tr)
        {
            if (null == tr)
                return "";
            var xamlstr1 = tr.GetText(DataFormats.Xaml);



            var xamlstr2 = xamlstr1.Replace("BaselineAlignment", "Typography.Variants");

            var tbTemp = new RichTextBox();
            var trTemp = new TextRange(tbTemp.Document.ContentStart, tbTemp.Document.ContentEnd);
            trTemp.SetText(xamlstr2, DataFormats.Xaml);

            return trTemp.GetText(DataFormats.Rtf);
        }

        public static void SetTextRtf(this TextRange tr, string rtfstr)
        {
            if (null == tr)
                return;
            if (string.IsNullOrEmpty(rtfstr))
            {
                tr.SetText(null, null);
                return;
            }

            var tbTemp = new RichTextBox();
            var trTemp = new TextRange(tbTemp.Document.ContentStart, tbTemp.Document.ContentEnd);
            trTemp.SetText(rtfstr, DataFormats.Rtf);

            var xamlstr2 = trTemp.GetText(DataFormats.Xaml);
            var regex = new Regex("Typography.Variants(?=(=\"(Superscript|Subscript)\"))");
            var xamlstr1 = regex.Replace(xamlstr2, "BaselineAlignment");

            tr.SetText(xamlstr1, DataFormats.Xaml);
        }

        public static TextRange TextRangeAll(this RichTextBox rtb)
        {
            if (null != rtb)
                return new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
            return null;
        }

        public static TextRange TextRangeAll(this TextBlock tb)
        {
            if (null != tb)
                return new TextRange(tb.ContentStart, tb.ContentEnd);
            return null;
        }
    }

注:當然,這裏只是解決了正確保存rtf的問題,右鍵複製RichTextBox再粘貼到Word中顯示錯誤的問題仍然沒有解決,但至少已經可以通過代碼向Word中添加正確的上下標字符信息了。

使用System.Windows.Forms.RichTextBox

在wpf中使用這個控件時,需要使用WinFormHost,具體的設置上下標,保存獲取代碼相當簡單,且Copy To Word也沒有任何問題。

設置上下標

richTextBox.SelectionCharOffset = 6; //設置上標
richTextBox.SelectionCharOffset = -6; //設置下標

rtf格式可在加載

strign val = richTextBox.Rtf; //獲取rtf格式的文本
richTextBox.Rtf = val; //設置rtf格式的文本
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章