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

支持 HTML 的 WPF TextBlock

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.36/5 (9投票s)

2009 年 2 月 7 日

LGPL3

2分钟阅读

viewsIcon

182566

downloadIcon

1115

本文描述了 HtmlTextBlock,它是一个 WPF TextBlock,可以解析有限的 HTML 标签并显示它们。

htmltextblock/mainscreen.jpg

引言

本文描述了 HtmlTextBlock,它是一个 WPF TextBlock,可以解析有限的 HTML 标签并显示它们。

背景

我正在开发一个自定义进度对话框,其中包含标题、消息、进度和一些操作按钮。

为了让它看起来更好,我希望消息支持一些文本格式,并且希望在运行时可以更改它,但使用 TextBlock 似乎是不可能的。

htmltextblock/background.jpg

然后我 Google 了如何在 WPF 中使用 HTML,但大多数解决方案告诉我使用 WebBrowser,这对于我的目的来说有点过头了。

然后我想起了一个几年前编写的废弃项目(主要是因为我转向了 WPF),它试图在 .NET 2 中重新创建 FlowDocument,并加载 HTML 文档(我的主要目的,该组件名为 QzMiniHtml2)。

令人惊讶的是,经过很少的修改(主要是使用 import),这个 .NET 2 项目可以很好地与 WPF 配合使用,就像您在上面看到的那样。

因此,原始项目也包含在内。

如何使用?

该控件类似于 TextBlock,只是您设置 HTML 属性而不是 Text
请记住使用 [ ] 方括号代替 < >

<Window x:Class="HtmlTextBlockTestProj.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uc="http://www.quickzip.org/UserControls"
    Title="HtmlTextBlockTest" Height="250" Width="450">
    <DockPanel>
        <uc:HtmlTextBlock Html="{Binding Text, ElementName=tb}"
                 DockPanel.Dock="Top" Loaded="HtmlTextBlock_Loaded" />
        <TextBlock Text="[b] [i] [u] [a href=xx] [br] supported."
                 DockPanel.Dock="Bottom" />
        <TextBox TextWrapping="Wrap" AcceptsReturn="True"
                  VerticalScrollBarVisibility="Visible"
                  x:Name="tb"
        Text="The [i][u]quick brown fox[/i][/u] jumps over the [b]lazy dog[/b]" />
    </DockPanel>
</Window>         

它是如何工作的?

该组件实际上包含一个 HTML 解析引擎,它将 HTML string 转换为 WPF 的粗体、斜体、下划线、超链接、行中断内联(未来可以添加更多,您可以轻松地自己完成,请参见下文)。

转换部分很简单。

1) private Inline UpdateElement(HtmlTag aTag)
2) {
3)   Inline retVal = null;

4)   switch (aTag.Name)
5)   {
6)     case "text" :
7)       retVal = new Run(aTag["value"]);
8)       if (currentState.Bold) retVal = new Bold(retVal);
9)       if (currentState.Italic) retVal = new Italic(retVal);
0)       if (currentState.Underline) retVal = new Underline(retVal);
A)       break;
B)     case "br" :
C)       retVal = new LineBreak();
D)       break;
E)   }

F)   if (currentState.HyperLink != null && currentState.HyperLink != "")
G)   {
H)     Hyperlink link = new Hyperlink(retVal);
I)     link.NavigateUri = new Uri(currentState.HyperLink);
J)     retVal = link;
K)   }
L)    return retVal;
M) }         

首先,请注意

  • 输入 (aTag) 是一个文本或行中断 (br),如果标签是文本,Tag["value"] 是它包含的文本。
    粗体、斜体等也可以由 HtmlTag 表示,但它们不会在这里执行。
  • CurrentState 包含影响 TextTag 等样式的状态。

所以如果标签是文本 (第 6 行)

  • 它将生成一个 Run(可以包含格式化或未格式化的文本,并且在本例中未格式化)(第 7 行)
  • 如果是粗体、斜体和下划线,它将构建它们,并使用最后一个内联 (抽象类,Run、Bold 等继承自它),因此它包含该属性。

当内联返回时 (第 L 行)

  • 它将被添加到您的 HtmlTextBlock.Inlines 集合中。

历史

  • 09-02-08 初始版本
© . All rights reserved.