包含超链接的 WPF RichTextBox






4.63/5 (5投票s)
创建支持超链接的自定义 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 日