65.9K
CodeProject 正在变化。 阅读更多。
Home

包含超链接的 WPF RichTextBox

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (5投票s)

2017 年 1 月 18 日

CPOL

2分钟阅读

viewsIcon

22441

downloadIcon

484

创建支持超链接的自定义 RichTextBox

下载示例

引言

在使用 Web 控件时,在一段文本中添加超链接非常容易。但使用 Windows 应用程序时,情况就没那么直接了。本文展示了如何修改 WPF RichTextBox 控件,以便在普通文本之间包含超链接。

背景

不久前,我的一个朋友正在开发一个包含大量文本内容的 Windows 应用程序。在文本内容中,他需要某些单词/ID 作为超链接,以便用户可以单击这些单词并导航到不同的页面(在本例中是一个网页),该页面可以显示与该单词相关的更多信息。

在使用 WPF 文本控件时,可以使用类似于以下代码的控件轻松包含超链接

<TextBlock> 
    <Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">Click here
     </Hyperlink>
</TextBlock>

但是,如果需要将超链接嵌入到动态绑定到视图的句子或文本段落中,则这种方法可能无法工作。类似于 #标签。

解决方案是创建一个支持此功能的自定义 RichTextBox 控件。

使用代码

此解决方案的基本组件是 CustomRichTextBox 控件,它是通过从普通的 RichTextBox 控件派生而创建的。该控件将具有 RichTextBox 控件的所有属性,以及一个名为“CustomText”的附加依赖属性,用于显示绑定到控件的文本内容。

public class CustomRichTextBox : RichTextBox
    {

        #region CustomText Dependency Property

        public static readonly DependencyProperty CustomTextProperty = DependencyProperty.Register("CustomText", typeof(string), typeof(CustomRichTextBox),
       new PropertyMetadata(string.Empty, CustomTextChangedCallback), CustomTextValidateCallback);

        private static void CustomTextChangedCallback(
            DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            (obj as CustomRichTextBox).Document = GetCustomDocument(e.NewValue as string);
        }

        private static bool CustomTextValidateCallback(object value)
        {
            return value != null;
        }

        public string CustomText
        {
            get
            {
                return (string)GetValue(CustomTextProperty);
            }
            set
            {
                SetValue(CustomTextProperty, value);
            }
        } 

        #endregion


        public CustomRichTextBox()
        {

        }

        private static  FlowDocument GetCustomDocument(string Text)
        {
            FlowDocument document = new FlowDocument();
            Paragraph para = new Paragraph();
            para.Margin = new Thickness(0); // remove indent between paragraphs
            foreach (string word in Text.Split(' ').ToList())
            {
                //This condition could be replaced by the Regex
                if(word.StartsWith("#"))
                {
                    string linkName = word.Substring(1, word.Length - 1);
                    //linkURL can be changed based on some condition.
                    string linkURL = GetUrl(linkName);
                   

                    Hyperlink link = new Hyperlink();
                    link.IsEnabled = true;
                    link.Inlines.Add(linkName);
                    link.NavigateUri = new Uri(linkURL);
                    link.RequestNavigate += (sender, args) => Process.Start(args.Uri.ToString());
                    para.Inlines.Add(link);
                }
                else
                {
                    para.Inlines.Add(word);
                }
                para.Inlines.Add(" ");
            }
            document.Blocks.Add(para);
            return document;
        }

        //This method may contain any logic to return a Url based on a key string
        static string GetUrl(string key)
        {
            return string.Format(@"https://www.google.com/#q={0}", key);
        }

    }

该方法 GetCustomDocument(string Text) 将控件绑定的文本中的每个单词拆分,如果在一个单词中遇到“#”前缀,它将动态创建一个超链接并将其添加到流文档中。

准备好 CustomRichTextBox 控件后,可以在视图 (xaml) 中使用它,并将其绑定到包含文本内容的属性,就像将内容绑定到文本控件一样。

<local:CustomRichTextBox IsDocumentEnabled="True" IsReadOnly="True" CustomText="{Binding Details}" /> 

就这样了…

对于下面的输入文本

“Lorem Ipsum 自 1500 年代以来一直是行业标准的虚拟 #Ford 文本。”

控件将按如下所示显示文本

该项目附带了本文,展示了在此控件在简单 WPF 应用程序中的完整用法。因此,您可以下载代码以查看控件的操作。

关注点

我尽可能地保持文章和示例项目简单易懂,即使是 WPF 新手也能轻松理解和修改。该方法也可以用于包含除超链接之外的其他控件。

对于 WPF 新手,在理解文章和代码后,以下是一些您应该熟悉的主题。

  • RichTextBox 控件概述
  • 创建 WPF 自定义控件
  • 添加和使用依赖属性
  • 数据模板的使用
  • 简单的 MVVM 绑定

历史

初始版本:2017 年 1 月 18 日

© . All rights reserved.