【WPF.NET开发】流文档
本文内容
- 什么是流文档?
- 流文档类型
- 创建流内容
- 与流相关的类
- 内容架构
- 自定义文本
流文档旨在优化查看和可读性。 流文档根据运行时变量(例如,窗口大小、设备分辨率和可选的用户首选项)来动态调整和重新排列内容,而不是设置为一个预定义的布局。 此外,流文档还提供一些高级文档功能,例如分页和分栏 本主题概述了流文档及其创建方式。
1、什么是流文档?
流文档旨在根据窗口大小、设备分辨率和其他环境变量来“重排内容”。 此外,流文档还具有很多内置功能,包括搜索、能够优化可读性的查看模式以及更改字体大小和外观的功能。 当易读性是文档的主要使用要求时,最适合使用流文档。 相反,固定文档旨在提供静态表示形式。 当源内容的保真度至关重要时,就适合使用固定文档。
下图演示在多个不同大小的窗口中查看同一个示例流文档的情况。 随着显示区域的变化,内容将重新布局,以充分利用可用空间。
如上图所示,流内容可包括多个组成部分,包括段落、列表、图像等等。 这些组成部分对应于标记中的元素和程序代码中的对象。 稍后,我们将在本概述的
与流相关的类部分中详细介绍这些类。 现在,我们提供一个简单的代码示例,该示例将创建一个由包含部分粗体文本的段落和列表组成的流文档。
<!-- This simple flow document includes a paragraph with somebold text in it and a list. -->
<FlowDocumentReader xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><FlowDocument><Paragraph><Bold>Some bold text in the paragraph.</Bold>Some text that is not bold.</Paragraph><List><ListItem><Paragraph>ListItem 1</Paragraph></ListItem><ListItem><Paragraph>ListItem 2</Paragraph></ListItem><ListItem><Paragraph>ListItem 3</Paragraph></ListItem></List></FlowDocument>
</FlowDocumentReader>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class SimpleFlowExample : Page{public SimpleFlowExample(){Paragraph myParagraph = new Paragraph();// Add some Bold text to the paragraphmyParagraph.Inlines.Add(new Bold(new Run("Some bold text in the paragraph.")));// Add some plain text to the paragraphmyParagraph.Inlines.Add(new Run(" Some text that is not bold."));// Create a List and populate with three list items.List myList = new List();// First create paragraphs to go into the list item.Paragraph paragraphListItem1 = new Paragraph(new Run("ListItem 1"));Paragraph paragraphListItem2 = new Paragraph(new Run("ListItem 2"));Paragraph paragraphListItem3 = new Paragraph(new Run("ListItem 3"));// Add ListItems with paragraphs in them.myList.ListItems.Add(new ListItem(paragraphListItem1));myList.ListItems.Add(new ListItem(paragraphListItem2));myList.ListItems.Add(new ListItem(paragraphListItem3));// Create a FlowDocument with the paragraph and list.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(myParagraph);myFlowDocument.Blocks.Add(myList);// Add the FlowDocument to a FlowDocumentReader ControlFlowDocumentReader myFlowDocumentReader = new FlowDocumentReader();myFlowDocumentReader.Document = myFlowDocument;this.Content = myFlowDocumentReader;}}
}
下图显示了此代码片段。
在此示例中,FlowDocumentReader 控件用于托管流内容。 Paragraph、List、ListItem 和 Bold 元素用于根据其在标记中的顺序来控制内容格式。 例如,Bold 元素只涵盖该段落中的一部分文本;因此,只有这一部分文本是粗体。 如果使用过 HTML,你就会了解这一点。
正如上图中突出显示的那样,流文档中有多个内置功能:
-
搜索:允许用户对整个文档执行全文搜索。
-
查看模式:用户可选择喜欢的查看模式,包括单页(一次一页)查看模式、一次两页(书本阅读格式)查看模式和连续滚动(无界限)查看模式。 有关这些查看模式的详细信息,请参阅 FlowDocumentReaderViewingMode。
-
页面导航控件:如果文档的查看模式使用页面,则页面导航控件包括一个用于跳转到下一页(向下键)或上一页(向上键)的按钮,以及显示当前页码和总页数的指示器。 也可使用键盘上的箭头键来实现翻页操作。
-
缩放:缩放控件可使用户通过单击加号或减号按钮来相应地增大或减小缩放级别。 缩放控件还包括一个用于调整缩放级别的滑块。
这些功能可根据用于托管流内容的控件进行修改。 下一节介绍了各种控件。
2、流文档类型
流文档内容的显示和外观依赖于用于托管流内容的对象。 有 4 个支持查看流内容的控件:FlowDocumentReader、FlowDocumentPageViewer、RichTextBox 和 FlowDocumentScrollViewer。 下面简要介绍了这些控件。
备注
需使用 FlowDocument 来直接托管流内容,因此所有这些查看控件都使用 FlowDocument 来启用流内容托管。
2.1 FlowDocumentReader
FlowDocumentReader 包含使用户能够动态选择各种查看模式的功能,这些查看模式包括单页(一次一页)查看模式、一次两页(书本阅读格式)查看模式和连续滚动(无界限)查看模式。 如果不需要在不同查看模式之间动态切换的功能,则可使用 FlowDocumentPageViewer 和 FlowDocumentScrollViewer,它们提供了固定使用特定查看模式的轻量级流内容查看器。
2.2 FlowDocumentPageViewer 和 FlowDocumentScrollViewer
FlowDocumentPageViewer 以一次一页的查看模式显示内容,而 FlowDocumentScrollViewer 以连续滚动模式显示内容。 FlowDocumentPageViewer 和 FlowDocumentScrollViewer 都固定使用特定查看模式。 相比之下,FlowDocumentReader 包含的功能使用户能够动态选择各种查看模式(由 FlowDocumentReaderViewingMode 枚举提供),但代价是需要消耗比 FlowDocumentPageViewer 或 FlowDocumentScrollViewer 更多的资源。
默认情况下,总是显示垂直滚动条,而水平滚动条则在需要时显示。 FlowDocumentScrollViewer 的默认 UI 不包括工具栏;不过,可使用 IsToolBarVisible 属性来启用内置工具栏。
2.3 RichTextBox
若要允许用户编辑流内容,请使用 RichTextBox。 例如,如果希望创建一个允许用户处理表、斜体和粗体格式等内容的编辑器,则应使用 RichTextBox。
备注
RichTextBox 内部的流内容行为与其他控件中包含的流内容行为并不完全相同。 例如,RichTextBox 中没有列,因此没有自动调整大小行为。 另外,在 RichTextBox 中不能使用通常内置在流内容中的功能,例如搜索、查看模式、页面导航和缩放。
3、创建流内容
流内容可能很复杂并包含各种元素,包括文本、图像、表甚至像控件这样的 UIElement 派生类。 若要了解如何创建复杂流内容,掌握下列知识点非常关键:
-
与流相关的类:流内容中使用的每个类都有特定用途。 此外,了解各种流类之间的层次关系有助于了解其使用方式。 例如,从 Block 类派生的类用于包含其他对象,而从 Inline 派生的类包含显示的对象。
-
内容架构:流文档可能需要大量嵌套元素。 内容架构指定了元素之间可能存在的父/子关系。
4、与流相关的类
下图演示了流内容中最常使用的对象:
根据流内容的用途,可分为两个重要类别:
-
Block 派生类:也称为“Block 内容元素”,或简称为“Block 元素”。 继承自 Block 的元素可用于将元素分组到一个公用父级下,或将公用属性应用于某个组。
-
Inline 派生类:也称为“Inline 内容元素”,或简称为“Inline 元素”。 继承自 Inline 的元素要么包含在 Block 元素中,要么包含在另一个 Inline 元素中。 Inline 元素通常用作在屏幕上呈现的内容的直接容器。 例如,Paragraph(Block 元素)可包含 Run(Inline 元素),而 Run 实际包含在屏幕上呈现的文本。
下面简要介绍了这两个类别中的每个类。
Block 派生类
Paragraph
Paragraph 常用于将内容分组到一个段落中。 Paragraph 的最简单且最常见的用途是创建文本段落。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Paragraph>Some paragraph text.</Paragraph>
</FlowDocument>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class ParagraphExample : Page{public ParagraphExample(){// Create paragraph with some text.Paragraph myParagraph = new Paragraph();myParagraph.Inlines.Add(new Run("Some paragraph text."));// Create a FlowDocument and add the paragraph to it.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(myParagraph);this.Content = myFlowDocument;}}
}
不过,也可以包含其他 Inline 派生元素,如下所示。
节
Section 只用于包含其他 Block 派生元素。 它不会向其中包含的元素应用任何默认格式。 但是,为 Section 设置的任何属性值都适用于其子元素。 使用节能够以编程方式循环访问其子集合。 Section 的使用方式类似于 HTML 中的 <DIV> 标记。
以下示例在一个 Section 下定义了 3 个段落。 该节具有 Background 属性值 Red,因此段落的背景色也是红色。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><!-- By default, Section applies no formatting to elements containedwithin it. However, in this example, the section has a Backgroundproperty value of "Red", therefore, the three paragraphs (the block) inside the section also have a red background. --><Section Background="Red"><Paragraph>Paragraph 1</Paragraph><Paragraph>Paragraph 2</Paragraph><Paragraph>Paragraph 3</Paragraph></Section>
</FlowDocument>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class SectionExample : Page{public SectionExample(){// Create three paragraphsParagraph myParagraph1 = new Paragraph(new Run("Paragraph 1"));Paragraph myParagraph2 = new Paragraph(new Run("Paragraph 2"));Paragraph myParagraph3 = new Paragraph(new Run("Paragraph 3"));// Create a Section and add the three paragraphs to it.Section mySection = new Section();mySection.Background = Brushes.Red;mySection.Blocks.Add(myParagraph1);mySection.Blocks.Add(myParagraph2);mySection.Blocks.Add(myParagraph3);// Create a FlowDocument and add the section to it.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(mySection);this.Content = myFlowDocument;}}
}
BlockUIContainer
BlockUIContainer 使 UIElement 元素(即 Button)能够嵌入到 Block 派生的流内容中。 InlineUIContainer(见下文)用于在 Inline 派生的流内容中嵌入 UIElement 元素。 BlockUIContainer 和 InlineUIContainer 很重要,因为除非 UIElement 包含在这两个元素之一中,否则没有其他办法在流内容中使用它。
以下示例演示如何使用 BlockUIContainer 元素在流内容中托管 UIElement 对象。
<FlowDocument ColumnWidth="400"><Section Background="GhostWhite"><Paragraph>A UIElement element may be embedded directly in flow contentby enclosing it in a BlockUIContainer element.</Paragraph><BlockUIContainer><Button>Click me!</Button></BlockUIContainer><Paragraph>The BlockUIContainer element may host no more than one top-levelUIElement. However, other UIElements may be nested within theUIElement contained by an BlockUIContainer element. For example,a StackPanel can be used to host multiple UIElement elements withina BlockUIContainer element.</Paragraph><BlockUIContainer><StackPanel><Label Foreground="Blue">Choose a value:</Label><ComboBox><ComboBoxItem IsSelected="True">a</ComboBoxItem><ComboBoxItem>b</ComboBoxItem><ComboBoxItem>c</ComboBoxItem></ComboBox><Label Foreground ="Red">Choose a value:</Label><StackPanel><RadioButton>x</RadioButton><RadioButton>y</RadioButton><RadioButton>z</RadioButton></StackPanel><Label>Enter a value:</Label><TextBox>A text editor embedded in flow content.</TextBox></StackPanel></BlockUIContainer></Section>
</FlowDocument>
下图显示了此示例的呈现效果:
列表
List 用于创建项目符号列表或编号列表。 将 MarkerStyle 属性设置为 TextMarkerStyle 枚举值可确定列表的样式。 下例演示了如何创建简单列表。
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class ListExample : Page{public ListExample(){// Create three paragraphsParagraph myParagraph1 = new Paragraph(new Run("List Item 1"));Paragraph myParagraph2 = new Paragraph(new Run("List Item 2"));Paragraph myParagraph3 = new Paragraph(new Run("List Item 3"));// Create the ListItem elements for the List and add the// paragraphs to them.ListItem myListItem1 = new ListItem();myListItem1.Blocks.Add(myParagraph1);ListItem myListItem2 = new ListItem();myListItem2.Blocks.Add(myParagraph2);ListItem myListItem3 = new ListItem();myListItem3.Blocks.Add(myParagraph3);// Create a List and add the three ListItems to it.List myList = new List();myList.ListItems.Add(myListItem1);myList.ListItems.Add(myListItem2);myList.ListItems.Add(myListItem3);// Create a FlowDocument and add the section to it.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(myList);this.Content = myFlowDocument;}}
}
备注
List 是唯一一个使用 ListItemCollection 来管理子元素的流元素。
表
Table 用于创建表。 Table 与 Grid 元素类似,但是前者具有更多功能,因此需要更大的资源开销。 因为 Grid 是一个 UIElement,所以除非它包含在 BlockUIContainer 或 InlineUIContainer 中,否则不能在流内容中使用。
Inline 派生类
运行
Run 用于包含无格式文本。 你可能会看到 Run 对象广泛用于流内容。 但是,在标记中,无需显式使用 Run 元素。 使用代码创建或操作流文档时,需使用 Run。 例如,在下面的标记中,第一个 Paragraph 显式指定了 Run 元素,而第二个却没有。 这两个段落生成相同的输出。
<Paragraph><Run>Paragraph that explicitly uses the Run element.</Run>
</Paragraph><Paragraph>This Paragraph omits the Run element in markup. It rendersthe same as a Paragraph with Run used explicitly.
</Paragraph>
备注
从 .NET Framework 4 开始,Run 对象的 Text 属性为依赖属性。 可将 Text 属性绑定到数据源,例如 TextBlock。 Text 属性完全支持单向绑定。 Text 属性还支持双向绑定,RichTextBox 除外。
Span
Span 将其他内联内容元素组合到一起。 对于 Span 元素中的内容,不应用任何固有呈现。 但是,从 Span 继承的元素(包括 Hyperlink、Bold、Italic 和 Underline)会向文本应用格式设置。
下面是 Span 的一个示例,它用于包含内联内容,包括文本、一个 Bold 元素和一个 Button。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Paragraph>Text before the Span. <Span Background="Red">Text within the Span isred and <Bold>this text is inside the Span-derived element Bold.</Bold>A Span can contain more then text, it can contain any inline content. Forexample, it can contain a <InlineUIContainer><Button>Button</Button></InlineUIContainer>or other UIElement, a Floater, a Figure, etc.</Span></Paragraph></FlowDocument>
下面的屏幕截图显示了此示例的呈现效果。
InlineUIContainer
InlineUIContainer 使 UIElement 元素(即 Button 这样的控件)能够嵌入到 Inline 内容元素中。 此元素是与上述 BlockUIContainer 等效的 Inline 元素。 以下示例使用 InlineUIContainer 将 Button 以内联方式插入 Paragraph 中。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Paragraph>Text to precede the button...<!-- Set the BaselineAlignment property to "Bottom" so that the Button aligns properly with the text. --><InlineUIContainer BaselineAlignment="Bottom"><Button>Button</Button></InlineUIContainer>Text to follow the button...</Paragraph></FlowDocument>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class InlineUIContainerExample : Page{public InlineUIContainerExample(){Run run1 = new Run(" Text to precede the button... ");Run run2 = new Run(" Text to follow the button... ");// Create a new button to be hosted in the paragraph.Button myButton = new Button();myButton.Content = "Click me!";// Create a new InlineUIContainer to contain the Button.InlineUIContainer myInlineUIContainer = new InlineUIContainer();// Set the BaselineAlignment property to "Bottom" so that the// Button aligns properly with the text.myInlineUIContainer.BaselineAlignment = BaselineAlignment.Bottom;// Asign the button as the UI container's child.myInlineUIContainer.Child = myButton;// Create the paragraph and add content to it.Paragraph myParagraph = new Paragraph();myParagraph.Inlines.Add(run1);myParagraph.Inlines.Add(myInlineUIContainer);myParagraph.Inlines.Add(run2);// Create a FlowDocument and add the paragraph to it.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(myParagraph);this.Content = myFlowDocument;}}
}
备注
不需要在标记中显式使用 InlineUIContainer。 如果将其省略,编译代码时仍将创建一个 InlineUIContainer。
Figure 和 Floater
通过 Figure 和 Floater,可使用位置属性在流文档中嵌入内容,这些属性可独立于主内容流进行自定义。 Figure 或 Floater 元素常用于突出显示或强调内容的某些部分,托管主内容流中的支持图像或其他内容,或用于注入松散相关的内容,例如广告。
以下示例演示如何将 Figure 嵌入文本段落中。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Paragraph><Figure Width="300" Height="100" Background="GhostWhite" HorizontalAnchor="PageLeft" ><Paragraph FontStyle="Italic" Background="Beige" Foreground="DarkGreen" >A Figure embeds content into flow content with placement properties that can be customized independently from the primary content flow</Paragraph></Figure>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummynibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisienim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortisnisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure.</Paragraph></FlowDocument>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;namespace SDKSample
{public partial class FigureExample : Page{public FigureExample(){// Create strings to use as content.string strFigure = "A Figure embeds content into flow content with" +" placement properties that can be customized" +" independently from the primary content flow";string strOther = "Lorem ipsum dolor sit amet, consectetuer adipiscing" +" elit, sed diam nonummy nibh euismod tincidunt ut laoreet" +" dolore magna aliquam erat volutpat. Ut wisi enim ad" +" minim veniam, quis nostrud exerci tation ullamcorper" +" suscipit lobortis nisl ut aliquip ex ea commodo consequat." +" Duis autem vel eum iriure.";// Create a Figure and assign content and layout properties to it.Figure myFigure = new Figure();myFigure.Width = new FigureLength(300);myFigure.Height = new FigureLength(100);myFigure.Background = Brushes.GhostWhite;myFigure.HorizontalAnchor = FigureHorizontalAnchor.PageLeft;Paragraph myFigureParagraph = new Paragraph(new Run(strFigure));myFigureParagraph.FontStyle = FontStyles.Italic;myFigureParagraph.Background = Brushes.Beige;myFigureParagraph.Foreground = Brushes.DarkGreen;myFigure.Blocks.Add(myFigureParagraph);// Create the paragraph and add content to it.Paragraph myParagraph = new Paragraph();myParagraph.Inlines.Add(myFigure);myParagraph.Inlines.Add(new Run(strOther));// Create a FlowDocument and add the paragraph to it.FlowDocument myFlowDocument = new FlowDocument();myFlowDocument.Blocks.Add(myParagraph);this.Content = myFlowDocument;}}
}
下图显示了此示例的呈现效果。
Figure 和 Floater 在多个方面存在差异,并用于不同的方案。
Figure:
-
可定位:可设置其水平和垂直定位点,以便相对于页面、内容、栏或段落进行停靠。 还可使用其 HorizontalOffset 和 VerticalOffset 属性指定任意偏移量。
-
可将其大小调整为列大小的几倍:可将 Figure 的高度和宽度设置为页面、内容或列的高度或宽度的倍数。 请注意,对于页面和内容,倍数不能大于 1。 例如,可将 Figure 的宽度设置为“页面的 0.5 倍”、“内容的 0.25 倍”或“列的 2 倍”。 还可将高度和宽度设置为绝对像素值。
-
不分页:如果 Figure 中的内容无法容纳在 Figure 内部,它会呈现能够容纳的内容部分,而其余内容将丢失。
Floater:
-
无法定位,可在能够为其提供空间的任何位置呈现。 不能设置偏移量或锚定 Floater。
-
不能将其大小调整为列大小的几倍:默认情况下,Floater 的大小为 1 个列大小。 它有一个可设置为绝对像素值的 Width 属性,但是如果此值大于 1 个列宽,则将其忽略并将浮动对象的大小调整为 1 个列大小。 可通过设置正确的像素宽度将其大小调整为小于 1 个列宽,但调整大小与列无关,因此“0.5 倍列宽”并不是 Floater 宽度的有效表达。 Floater 没有高度属性,无法设置其高度;其高度取决于内容
-
Floater 分页:如果指定宽度的内容超出了 1 个列高,则浮动对象会断开并显示到下一列、下一页等。
Figure 适合放置希望控制其大小和位置的独立内容,并且可以确信内容适合指定的大小。 Floater 适合放置流动更加自由的内容,其流动方式与主页内容类似,但与主页内容相分离。
LineBreak
LineBreak 导致在流内容中发生换行。 以下示例演示了 LineBreak 的用法。
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Paragraph>Before the LineBreak in Paragraph.<LineBreak />After the LineBreak in Paragraph.<LineBreak/><LineBreak/>After two LineBreaks in Paragraph.</Paragraph><Paragraph><LineBreak/></Paragraph><Paragraph>After a Paragraph with only a LineBreak in it.</Paragraph>
</FlowDocument>
下面的屏幕截图显示了此示例的呈现效果。
流集合元素
在上面的多个示例中,BlockCollection 和 InlineCollection 用于以编程方式构造流内容。 例如,若要向 Paragraph 添加元素,可使用以下语法:
myParagraph.Inlines.Add(new Run("Some text"));
这会将 Run 添加到 Paragraph 的 InlineCollection。 这与标记中的 Paragraph 内部包含的隐式 Run 相同:
<Paragraph>
Some Text
</Paragraph>
作为使用 BlockCollection 的示例,以下示例创建了一个新的 Section,然后使用 Add 方法将一个新的 Paragraph 添加到 Section 内容中。
Section secx = new Section();
secx.Blocks.Add(new Paragraph(new Run("A bit of text content...")));
除向流集合中添加项之外,还可以移除项。 下面的示例删除 Span 中的最后一个 Inline 元素。
spanx.Inlines.Remove(spanx.Inlines.LastInline);
以下示例将从 Span 中清除所有内容(Inline 元素)。
spanx.Inlines.Clear();
以编程方式使用流内容时,可能会广泛使用这些集合。
流元素是使用 InlineCollection (Inline) 还是 BlockCollection (Block) 来包含其子元素取决于父级可以包含的子元素类型(Block 或 Inline)。 下一节中的内容架构中概述了流内容元素的包容规则。
备注
还有第三种类型的集合可用于流内容,即 ListItemCollection,但此集合仅用于 List。 此外,还有几个可用于 Table 的集合。
5、内容架构
不同流内容元素的数量是如此之多,因此了解某个元素可包含的子元素类型非常困难。 下面的关系图概述了流元素的包容规则。 箭头表示可能存在的父/子关系。
如上面的关系图所示,元素可以具有的子元素不一定通过该元素是 Block 元素还是 Inline 元素来确定。 例如,Span(Inline 元素)只能具有 Inline 子元素,而 Figure(也是 Inline 元素)只能具有 Block 子元素。 因此,关系图可用于快速确定哪些元素可以包含在其他元素中。 例如,可使用关系图来确定如何构造 RichTextBox 的流内容。
1.RichTextBox 必须包含 FlowDocument,而后者又必须包含 Block 派生对象。 下面是上述关系图中的对应部分。
到此为止,标记可能类似于所示内容。
<RichTextBox><FlowDocument><!-- One or more Block-derived object… --></FlowDocument>
</RichTextBox>
2. 按照该关系图,存在多个可从中进行选择的 Block 元素,包括 Paragraph、Section、Table、List 和 BlockUIContainer(请参阅上面的 Block 派生类)。 假设需要一个 Table。 按照上面的关系图,Table 包含一个 TableRowGroup,后者包含 TableRow 元素,这些元素又包含 TableCell 元素,而这些元素包含一个 Block 派生对象。 下面是取自上述关系图中 Table 的对应部分。
下面是对应的标记。
<RichTextBox><FlowDocument><Table><TableRowGroup><TableRow><TableCell><!-- One or more Block-derived object… --></TableCell></TableRow></TableRowGroup></Table></FlowDocument>
</RichTextBox>
3. 同样,TableCell 下需要一个或多个 Block 元素。 为简单起见,在单元格内部放置一些文本。 可以使用带有 Run 元素的 Paragraph 来实现该操作。 下面是该关系图中的对应部分,它显示 Paragraph 可以包含 Inline 元素,而 Run(Inline 元素)只能包含纯文本。
下面是标记中的完整示例。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><RichTextBox><FlowDocument><!-- Normally a table would have multiple rows and multiplecells but this code is for demonstration purposes.--><Table><TableRowGroup><TableRow><TableCell><Paragraph><!-- The schema does not actually requireexplicit use of the Run tag in markup. It is only included here for clarity. --><Run>Paragraph in a Table Cell.</Run></Paragraph></TableCell></TableRow></TableRowGroup></Table></FlowDocument></RichTextBox>
</Page>
6、自定义文本
通常,文本是流文档中最普遍的内容类型。 尽管上面介绍的对象可用于控制文本呈现方式的大多数方面,但本文还介绍了其他一些自定义文本的方法。
文本修饰
使用文本修饰,可向文本应用下划线、上划线、基线和删除线效果(请参见下图)。 这些修饰是使用 TextDecorations 属性添加的,该属性由许多对象公开,其中包括 Inline、Paragraph、TextBlock 和 TextBox。
以下示例演示如何设置 TextDecorations 的 Paragraph 属性。
<FlowDocument ColumnWidth="200"><Paragraph TextDecorations="Strikethrough">This text will render with the strikethrough effect.</Paragraph>
</FlowDocument>
Paragraph parx = new Paragraph(new Run("This text will render with the strikethrough effect."));
parx.TextDecorations = TextDecorations.Strikethrough;
下图显示了此示例的呈现效果。
下面各图分别显示了上划线、基线和下划线修饰的呈现效果。
版式
Typography 属性由大多数与流相关的内容公开,其中包括 TextElement、FlowDocument、TextBlock 和 TextBox。 此属性用于控制文本的版式特征/变体(即小型大写字母或大型大写字母、设置上标和下标等)。
以下示例将 Paragraph 作为示例元素,演示如何设置 Typography 属性。
<ParagraphTextAlignment="Left"FontSize="18" FontFamily="Palatino Linotype"Typography.NumeralStyle="OldStyle"Typography.Fraction="Stacked"Typography.Variants="Inferior"
><Run>This text has some altered typography characteristics. Notethat use of an open type font is necessary for most typographicproperties to be effective.</Run><LineBreak/><LineBreak/><Run>0123456789 10 11 12 13</Run><LineBreak/><LineBreak/><Run>1/2 2/3 3/4</Run>
</Paragraph>
下图显示了此示例的呈现效果。
与此相反,下图显示了一个具有默认版式属性的类似示例的呈现效果。
下面的示例演示如何以编程方式设置 Typography 属性。
相关文章:

【WPF.NET开发】流文档
本文内容 什么是流文档?流文档类型创建流内容与流相关的类内容架构自定义文本 流文档旨在优化查看和可读性。 流文档根据运行时变量(例如,窗口大小、设备分辨率和可选的用户首选项)来动态调整和重新排列内容,而不是设…...
golang学习-结构体
1、定义 使用type 和struct 关键字来定义结构体,是值类型 格式如下: type 类型名 struct { 字段名 类型 字段名 类型 ... } 2、实例化 1、var 结构体实例 结构体类型 var p1 Person 2、使用new关键字 var p2 new(Person) 3、使用&对结构体…...
Python:enumerate() 函数
enumerate() 函数用于同时遍历索引和元素,常用于循环中。这个函数返回一个包含索引和元素的元组,可以通过解包的方式获取它们。 使用方法: enumerate(iterable, start0). iterable: 要遍历的可迭代对象。start: 索引起始值,默认…...

FPGA 移位运算与乘法
题目: 已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效) 由题意可知: 复位信号高有效,低复位;在inpu_grant上升…...

网络安全B模块(笔记详解)- MYSQL信息收集
MYSQL信息收集 1.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL03进行服务信息扫描渗透测试(使用工具Nmap,使用必须要使用的参数),并将该操作显示结果中数据库版本信息作为Flag提交; Flag:MySQL 5.5.12 2.通过渗透机场景Kali中的渗透测试工具对服务器场景MySQL0…...
从JavaScript的角度上讲解一下xml
- XML(可扩展标记语言) XML(可扩展标记语言)是一种被设计用于存储和传输结构化数据的标记语言。它与HTML相似,但XML并没有预定义的标签,可以自定义标签及其属性。从JavaScript的角度来看,XML可以…...
Pandas实战100例 | 案例 13: 数据分类 - 使用 `cut` 对数值进行分箱
案例 13: 数据分类 - 使用 cut 对数值进行分箱 知识点讲解 在数据分析中,将连续的数值数据分类成不同的区间(或“分箱”)是一种常见的做法。Pandas 提供了 cut 函数,它可以根据你指定的分箱边界将数值数据分配到不同的类别中。 …...

python统计分析——操作案例(模拟抽样)
参考资料:用python动手学统计学 import numpy as np import pandas as pd from matplotlib import pyplot as plt import seaborn as snsdata_setpd.read_csv(r"C:\python统计学\3-4-1-fish_length_100000.csv")[length] #此处将文件路径改为自己的路…...

部署Tomcat及其负载均衡
Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。一般来说,Tomcat虽然和Apache或者Nginx这些Web服务器一样…...
C++ 类、结构体
C 类、结构体 类可以将变量、数组和函数完美地打包在一起。 类与结构体 类的定义: class Person {private:int age,height;double money;string books[100];public:string name;void say(){cout<<"Im"<<name<<endl;}int get_age(){…...

数据结构(三)堆和哈希表
目录 哈希表和堆什么是哈希表 ?什么是堆 ?什么是图 ?案例一:使用python实现最小堆案例二 : 如何用Python通过哈希表的方式完成商品库存管理闯关题 (包含案例三:python实现哈希表) 本…...

李宏毅LLM——ChatGPT原理剖析
文章目录 Chat-GPT引言关键技术——预训练研究问题玩文字冒险游戏 ChatGPT原理剖析 Chat-GPT引言 直观感受:结果有模有样、每次输出结果都不同、可以追问、幻想出的答案误解:罐头回答、答案是网络搜索的结果真正做的事:文字接龙,…...
让Windows上vscode的C语言scanf函数可以读取中文字符
windows的默认字符集保存为GBK不要修改 区域设置–时钟和区域–区域–管理–更系统区域设置–(不要勾选)使用UTF-8。 查看验证当前字符集: cmdchcp 活动代码页: 936936就是简体中文GBK vscode的setting.json文件添加如下代码 点击左下角…...

Linux命令(3)
一. tr 对字符进行处理: tr 命令用于字符转换、替换和删除,主要用于删除文件中的控制符或进行字符串转换等。 将a转换成1 将小写字母转换成大写 压缩: tr -s 将a压缩成一个a 将空格压缩成一个 删除: tr -d 补集: 用字符串中的字符集的补…...
安卓MediaRecorder(3)音频采集编码写入详细源码分析
文章目录 前言音频采集音频初始化AudioRecord 分析AudioSource 采集到音频 音频编码音频编码后数据处理MPEG4Writer写入音频编码后数据到文件MPEG4Writer::Track 取编码后的音频编数据结语 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134896808 最新更新地…...
2024年网络安全竞赛—网络安全事件分析应急响应解析(包含FLAG)
网络安全事件分析应急响应 目录 网络安全事件分析应急响应 解析如下:...

FineBI实战项目一(22):各省份订单个数及订单总额分析开发
点击新建组件,创建各省份订单个数及订单总额组件。 选择自定义图表,将province拖拽到横轴,将cnt和total拖拽到纵轴。 调节纵轴的为指标并列。 修改横轴和纵轴的标题。 修改柱状图样式: 将组件拖拽到仪表板。 结果如下:…...
2024.1.16 调用tinyspline样条曲线拟合库时报 stack smashing detected,CMakeLists.txt中屏蔽该异常
在函数中调用第三方库api拟合样条曲线,函数中一切正常,可以打印所有数组变量,重复执行该函数,某一次函数return时报 stack smashing deteced (unknown) ,原因可能是第三方库内部的函数有栈溢出风…...

Leetcode202快乐数(java实现)
今天分享的题目是快乐数: 快乐数的定义如下: 快乐数(Happy Number)是指一个正整数,将其替换为各个位上数字的平方和,重复这个过程直到最后得到的结果为1,或者无限循环但不包含1。如果最终结果为…...
50天精通Golang(第13天)
反射reflect 一、引入 先看官方Doc中Rob Pike给出的关于反射的定义: Reflection in computing is the ability of a program to examine its own structure, particularly through types; it’s a form of metaprogramming. It’s also a great source of confus…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...