一:背景 1. 講故事 最近在分析dump時,發現有程式的卡死和WeakReference有關,在以前只知道怎麼用,但不清楚底層邏輯走向是什麼樣的,藉著這個dump的契機來簡單研究下。 二:弱引用的玩法 1. 一些基礎概念 用過WeakReference的朋友都知道這裡面又可以分為弱短和弱長兩個概念 ...
動手寫一個簡單的消息對話框一文介紹瞭如何實現滿足常見應用場景的消息對話框。但是內容區域的文字僅僅起到信息展示作用,對於需要部分關鍵字高亮,或者部分內容有交互性的場景(例如下圖提示信息中的“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達到跳轉效果。
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.NavigationWindow
、System.Windows.Controls.Frame
或任何可承載 XBAP 的瀏覽器(包括 Internet Explorer 7、Microsoft Internet Explorer 6 和 Firefox2.0 以上版本)。因此,需要對這段代碼稍作修改。
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;
}