[WPF]用HtmlTextBlock实现消息对话框的内容高亮和跳转

动手写一个简单的消息对话框一文介绍了如何实现满足常见应用场景的消息对话框。但是内容区域的文字仅仅起到信息展示作用,对于需要部分关键字高亮,或者部分内容有交互性的场景(例如下图提示信息中的"what's the risk?"需要跳转)则无能为力了。本文将介绍如何在WPF中灵活的实现消息对话框中局部文字内容高亮或者支持跳转。

HtmlTextBlock的使用

在WPF中,可以采用<Run>或者TextEffect实现文字中部分关键字高亮,但无法同时满足部分内容支持链接跳转功能 。如果能直接使用HTML,问题就迎刃而解了,但是在消息对话框的内容区域放一个webbrowser或cef浏览器有点太臃肿了。WPF HTML Supported TextBlock分享了一个支持有限HTML标签的WPF控件。该控件可以支持<b>,<u>,<i>,<a>,<br>,<font>标签,派生自TextBlock控件,并新增了一个依赖属性HtmlProperty接收需要展现的html内容,使用时需要把html内容字符串中的<>[]代替。

Content="[font color=red]红色[/font]文字高亮";

<toolkit:HtmlTextBlock Margin="0,0,0,0" FontSize="18"
					   HorizontalAlignment="Center" VerticalAlignment="Center" 
					   Html="{Binding Content}" />

需要注意的是,用Html绑定的内容中如果包含成对的英文方括号[]都会被当做标签处理,无论是否是上述支持的六种标签,都不会显示出来。中文方括号【】或者单个的英文方括号则会作为内容直接显示出来。如果用Text绑定内容则全部当成内容显示出来。

修改消息对话框

动手写一个简单的消息对话框中内容区域是使用可选中文本的控件SelectableTextBlock显示内容,只需全部替换为HtmlTextBlock,并用依赖属性HtmlProperty绑定内容即可。调用的时候只需把内容改为带标签的内容即可。例如:

 ShowAlertDialog(AlertDialogMode.Normal, AlertDialogType.Info, "打开[a href=https://www.chinadaily.com.cn/]中国日报[/a]网站", yesbuttonText: "确定", nobuttonText: "取消", parent: this);

但在使用<a>标签实现链接跳转时并没有用浏览器打开指定页面,调试过程中发现以下关键代码,可以看到HtmlTextBlock是把<a>转换为Hyperlink控件,并把href中的url赋值给NavigateUri达到跳转效果。

c# 复制代码
private Inline UpdateElement(HtmlTag aTag)
{
  Inline retVal = null;

  switch (aTag.Name)
  {
    case "text" :
      retVal = new Run(aTag["value"]);
      if (currentState.Bold) retVal = new Bold(retVal);
      if (currentState.Italic) retVal = new Italic(retVal);
      if (currentState.Underline) retVal = new Underline(retVal);
      break;
    case "br" :
      retVal = new LineBreak();
      break;
  }

  if (currentState.HyperLink != null && currentState.HyperLink != "")
  {
    Hyperlink link = new Hyperlink(retVal);
    link.NavigateUri = new Uri(currentState.HyperLink);
    retVal = link;
  }
   return retVal;
}

然而,只有 Hyperlink的直接或间接父级为导航宿主时,Hyperlink才能导航到NavigateUri属性的值,导航宿主包括System.Windows.Navigation.NavigationWindowSystem.Windows.Controls.Frame或任何可承载 XBAP 的浏览器(包括 Internet Explorer 7、Microsoft Internet Explorer 6 和 Firefox2.0 以上版本)。因此,需要对这段代码稍作修改。

c# 复制代码
if (currentState.HyperLink != null && currentState.HyperLink.Length > 0)
{
	Hyperlink link = new Hyperlink(retVal);
	try
	{
		link.Click += new RoutedEventHandler((s, e) =>
		{
			Process.Start(new ProcessStartInfo((s as Hyperlink).NavigateUri.AbsoluteUri));
			e.Handled = true;
		});
	}
	catch(Exception ex)
	{
		.....
	}
	retVal = link;
}
相关推荐
九鼎科技-Leo10 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
麻花201320 小时前
C#之WPF的C1FlexGrid空间的行加载事件和列事件变更处理动态加载的枚举值
开发语言·c#·wpf
lcintj20 小时前
【WPF】Prism学习(九)
学习·wpf·prism
界面开发小八哥20 小时前
界面控件DevExpress WPF中文教程:网格视图数据布局的列和卡片字段
wpf·界面控件·devexpress·ui开发·用户界面
△曉風殘月〆20 小时前
如何在WPF中嵌入其它程序
wpf
Crazy Struggle20 小时前
功能齐全的 WPF 自定义控件资源库(收藏版)
.net·wpf·ui控件库
shepherd枸杞泡茶1 天前
WPF动画
c#·.net·wpf
lcintj1 天前
【WPF】Prism学习(十)
学习·wpf·prism
wyh要好好学习1 天前
WPF数据加载时添加进度条
ui·wpf
code_shenbing1 天前
跨平台WPF框架Avalonia教程 三
前端·microsoft·ui·c#·wpf·跨平台·界面设计