共用方式為


非固定格式文件概觀

非固定格式文件 (Flow Document) 是設計來最佳化檢視和可讀性。 非固定格式文件並不會設為某種預先定義的配置,而是會根據執行階段變數 (如視窗大小、裝置解析度和選擇性的使用者偏好設定),動態調整及重新排列其內容。 此外,非固定格式文件提供進階的文件功能,例如分頁和欄位。 本主題提供非固定格式文件的概觀及建立的方式。

這個主題包含下列章節。

  • 什麼是非固定格式文件
  • 非固定格式文件類型
  • 建立非固定格式內容
  • 非固定格式相關類別
  • 內容結構描述
  • 自訂文字
  • 相關主題

什麼是非固定格式文件

非固定格式文件可以根據視窗大小、裝置解析度及其他環境變數來「重新排列內容」。 此外,非固定格式文件具備許多內建功能,包括搜尋、將可讀性最佳化的檢視模式,以及變更字型大小與外觀的能力。 當文件使用上的主要考量是容易閱讀的時候,利用非固定格式文件是最好的方法。 相反地,固定格式文件是針對靜態展示設計。 固定格式文件在必須精確呈現來源內容時相當有用。 如需不同類型文件的詳細資訊,請參閱 WPF 中的文件

下圖顯示在數種不同大小的視窗中檢視的非固定格式文件範例。 當顯示區域變更時,內容就會重新排列以運用可用的空間。

非固定格式文件內容重新排列

如同上圖所示,非固定格式內容可以包含許多元件,包括段落、清單、影像等等。 這些元件對應至標記 (Markup) 中的項目及程式碼中的物件。 我們稍後會在這篇簡介非固定格式相關類別章節中詳細說明這些類別。 現在,請先參考這個簡單的程式碼範例,它會建立非固定格式文件,其中含有一個具部分粗體字的段落和一份清單。

<!-- This simple flow document includes a paragraph with some
     bold text in it and a list. -->
<FlowDocumentReader xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://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>

Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class SimpleFlowExample
        Inherits Page
        Public Sub New()

            Dim myParagraph As New Paragraph()

            ' Add some Bold text to the paragraph
            myParagraph.Inlines.Add(New Bold(New Run("Some bold text in the paragraph.")))

            ' Add some plain text to the paragraph
            myParagraph.Inlines.Add(New Run(" Some text that is not bold."))

            ' Create a List and populate with three list items.
            Dim myList As New List()

            ' First create paragraphs to go into the list item.
            Dim paragraphListItem1 As New Paragraph(New Run("ListItem 1"))
            Dim paragraphListItem2 As New Paragraph(New Run("ListItem 2"))
            Dim paragraphListItem3 As 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.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(myParagraph)
            myFlowDocument.Blocks.Add(myList)

            ' Add the FlowDocument to a FlowDocumentReader Control
            Dim myFlowDocumentReader As New FlowDocumentReader()
            myFlowDocumentReader.Document = myFlowDocument

            Me.Content = myFlowDocumentReader
        End Sub
    End Class
End Namespace
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 paragraph
            myParagraph.Inlines.Add(new Bold(new Run("Some bold text in the paragraph.")));

            // Add some plain text to the paragraph
            myParagraph.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 Control
            FlowDocumentReader myFlowDocumentReader = new FlowDocumentReader();
            myFlowDocumentReader.Document = myFlowDocument;

            this.Content = myFlowDocumentReader;
        }
    }
}

下圖顯示這個程式碼片段的外觀。

螢幕擷取畫面:呈現的 FlowDocument 範例

在這個範例中,FlowDocumentReader 控制項是用於裝載非固定格式文件。 如需非固定格式文件裝載控制項的詳細資訊,請參閱非固定格式文件類型。 ParagraphListListItemBold 項目根據它們在標記 (Markup) 中的順序,來調整內容的顯示格式。 例如,Bold 項目只包住段落中的部分文字,結果就只有這部分的文字會呈現粗體。 如果您使用過 HTML,對這一點應該相當熟悉。

如同在上圖中所強調的,非固定格式文件中有許多內建功能:

  • 搜尋:讓使用者對整份文件執行全文檢索搜尋。

  • 檢視模式:使用者可以選取偏好的檢視模式,包括單頁 (一次顯示一頁) 檢視模式、雙頁 (書本閱讀格式) 檢視模式,以及連續捲動 (無底邊) 檢視模式。 如需這些檢視模式的詳細資訊,請參閱 FlowDocumentReaderViewingMode

  • 頁面巡覽控制項:如果文件的檢視模式使用頁面,頁面巡覽控制項會包含可跳到下一頁 (向下箭號) 或上一頁 (向上箭號) 的按鈕,以及顯示目前頁碼與總頁數的指示區。 翻頁的動作也可以使用鍵盤方向鍵來完成。

  • 縮放:縮放控制項可讓使用者按下加號或減號按鈕來增加或減少縮放層級。 縮放控制項也包含可用於調整縮放層級的滑桿。 如需詳細資訊,請參閱 Zoom

這些功能可以根據用於裝載非固定格式內容的控制項來修改。 下一節會說明其他控制項。

非固定格式文件類型

非固定格式文件內容的顯示和出現方式,取決於用來裝載非固定格式內容的物件。 有四個控制項支援檢視非固定格式內容:FlowDocumentReaderFlowDocumentPageViewerRichTextBoxFlowDocumentScrollViewer。 這些控制項的簡略說明如下。

注意:直接裝載非固定格式內容時需要 FlowDocument,所以所有檢視控制項都會使用 FlowDocument 裝載非固定格式內容。

FlowDocumentReader

FlowDocumentReader 包含可讓使用者動態選擇各種檢視模式的功能,包括單頁 (一次顯示一頁) 檢視模式、雙頁 (書本閱讀格式) 檢視模式,以及連續捲動 (無底邊) 檢視模式。 如需這些檢視模式的詳細資訊,請參閱 FlowDocumentReaderViewingMode。 如果您不需要動態切換不同檢視模式的功能,則 FlowDocumentPageViewerFlowDocumentScrollViewer 可提供較輕量的非固定格式內容檢視器,這兩種會固定使用特定的檢視模式。

FlowDocumentPageViewer 和 FlowDocumentScrollViewer

FlowDocumentPageViewer 會以一次顯示一頁的檢視模式顯示內容,而 FlowDocumentScrollViewer 會以連續捲動模式顯示內容。 FlowDocumentPageViewerFlowDocumentScrollViewer 都有固定的特定檢視模式。 相較之下,FlowDocumentReader 包含的功能可讓使用者動態選擇各種檢視模式 (如 FlowDocumentReaderViewingMode 列舉型別所提供),但代價是比 FlowDocumentPageViewerFlowDocumentScrollViewer 需要更多資源。

預設一定會顯示垂直捲軸,而水平捲動會視需要顯示。 FlowDocumentScrollViewer 的預設 UI 不包含工具列,不過,您可以使用 IsToolBarVisible 屬性啟用內建工具列。

RichTextBox

當您要讓使用者編輯非固定格式內容時,使用 RichTextBox。 例如,如果您要建立編輯器,讓使用者管理像是表格、斜體或粗體格式等等項目,請使用 RichTextBox。 如需詳細資訊,請參閱 RichTextBox 概觀

注意RichTextBox 內的非固定格式內容展現的行為與其他控制項中的非固定格式內容不完全相同。 例如,RichTextBox 中並沒有欄位,因此不會有自動調整大小的行為。 此外,RichTextBox 內沒有非固定格式內容的典型內建功能,例如搜尋、檢視模式、頁面巡覽及縮放等等。

建立非固定格式內容

非固定格式內容可以是複雜的,由各種項目組成,包括文字、影像、表格,甚至是像控制項的 UIElement 衍生類別 (Derived Class)。 若要了解如何建立複雜的非固定格式內容,必須了解下列幾點:

  • 非固定格式相關類別:非固定格式內容中使用的每個類別都有特定目的。 此外,非固定格式類別之間的階層關係可以協助您了解其使用方式。 例如,從 Block 衍生的類別是用於包含其他物件,而從 Inline 衍生的類別則包含顯示的物件。

  • 內容結構描述:非固定格式文件可能需要大量的巢狀項目。 內容結構描述會指定項目之間可能的父代/子系關係。

下列各節會針對各個部分做詳細說明。

非固定格式相關類別

下圖顯示非固定格式內容中最常使用的物件:

圖表:非固定格式內容項目類別階層架構

就非固定格式內容用途,有兩個重要分類:

  1. Block 衍生類別:也稱為「Block 內容項目」或只稱為「Block 項目」。 繼承自 Block 的項目可以用來將共同父代下的項目放在一起形成群組,或將共同屬性套用至群組。

  2. Inline 衍生類別:也稱為「Inline 內容項目」或只稱為「Inline 項目」。 繼承自 Inline 的項目會包含在「Block 項目」內或其他「Inline 項目」內。 「Inline 項目」通常做為直接呈現至螢幕之內容的直接容器 (Container)。 例如,Paragraph (Block 項目) 可以包含 Run (Inline 項目),而 Run 則包含螢幕上呈現的文字。

這兩個分類中的每個類別會簡略說明如下。

Block 衍生類別

Paragraph

Paragraph 通常用於將內容分組成段落。 Paragraph 最簡單和最常見的用途是建立文字段落。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Paragraph>
    Some paragraph text.
  </Paragraph>
</FlowDocument>

Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class ParagraphExample
        Inherits Page
        Public Sub New()

            ' Create paragraph with some text.
            Dim myParagraph As New Paragraph()
            myParagraph.Inlines.Add(New Run("Some paragraph text."))

            ' Create a FlowDocument and add the paragraph to it.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(myParagraph)

            Me.Content = myFlowDocument
        End Sub
    End Class
End Namespace
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 底下定義了三個段落 (Paragraph)。 區段的 Background 屬性值為 Red,因此段落的背景色彩也會是紅色的。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <!-- By default, Section applies no formatting to elements contained
       within it. However, in this example, the section has a Background
       property 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>

Imports System
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class SectionExample
        Inherits Page
        Public Sub New()

            ' Create three paragraphs
            Dim myParagraph1 As New Paragraph(New Run("Paragraph 1"))
            Dim myParagraph2 As New Paragraph(New Run("Paragraph 2"))
            Dim myParagraph3 As New Paragraph(New Run("Paragraph 3"))

            ' Create a Section and add the three paragraphs to it.
            Dim mySection As 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.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(mySection)

            Me.Content = myFlowDocument
        End Sub
    End Class
End Namespace
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 paragraphs
            Paragraph 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 (請參閱以下內容) 是用於將 UIElement 項目內嵌至 Inline 衍生非固定格式內容。 BlockUIContainerInlineUIContainer 相當重要,因為沒有其他方式可以在非固定格式內容中使用 UIElement,除非是包含在這兩個項目之一。

下列範例顯示如何使用 BlockUIContainer 項目,在非固定格式內容內裝載 UIElement 物件。

<FlowDocument ColumnWidth="400">
  <Section Background="GhostWhite">
    <Paragraph>
      A UIElement element may be embedded directly in flow content
      by enclosing it in a BlockUIContainer element.
    </Paragraph>
    <BlockUIContainer>
      <Button>Click me!</Button>
    </BlockUIContainer>
    <Paragraph>
      The BlockUIContainer element may host no more than one top-level
      UIElement.  However, other UIElements may be nested within the
      UIElement contained by an BlockUIContainer element.  For example,
      a StackPanel can be used to host multiple UIElement elements within
      a 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>

下圖顯示這個範例呈現的效果。

螢幕擷取畫面:內嵌於非固定格式內容中的 UIElement

List

List 是用於建立項目符號或數值清單。 將 MarkerStyle 屬性設為 TextMarkerStyle 列舉值會決定清單的樣式。 下列範例會顯示如何建立簡單的清單。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <List>
    <ListItem>
      <Paragraph>
        List Item 1
      </Paragraph>
    </ListItem>
    <ListItem>
      <Paragraph>
        List Item 2
      </Paragraph>
    </ListItem>
    <ListItem>
      <Paragraph>
        List Item 3
      </Paragraph>
    </ListItem>
  </List>
</FlowDocument>

Imports System
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class ListExample
        Inherits Page
        Public Sub New()

            ' Create three paragraphs
            Dim myParagraph1 As New Paragraph(New Run("List Item 1"))
            Dim myParagraph2 As New Paragraph(New Run("List Item 2"))
            Dim myParagraph3 As New Paragraph(New Run("List Item 3"))

            ' Create the ListItem elements for the List and add the 
            ' paragraphs to them.
            Dim myListItem1 As New ListItem()
            myListItem1.Blocks.Add(myParagraph1)
            Dim myListItem2 As New ListItem()
            myListItem2.Blocks.Add(myParagraph2)
            Dim myListItem3 As New ListItem()
            myListItem3.Blocks.Add(myParagraph3)

            ' Create a List and add the three ListItems to it.
            Dim myList As New List()

            myList.ListItems.Add(myListItem1)
            myList.ListItems.Add(myListItem2)
            myList.ListItems.Add(myListItem3)

            ' Create a FlowDocument and add the section to it.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(myList)

            Me.Content = myFlowDocument
        End Sub
    End Class
End Namespace
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 paragraphs
            Paragraph 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 項目,但其功能較多,因此需要更多資源負荷。 因為 GridUIElement,所以無法在非固定格式內容中使用,除非是包含在 BlockUIContainerInlineUIContainer。 如需 Table 的詳細資訊,請參閱資料表概觀

Inline 衍生類別

回合

Run 是用來包含未格式化的文字。 您可能預期 Run 物件會廣泛用在動態內容中。 不過在標記中,不需要明確使用 Run 項目。 使用程式碼建立或管理非固定格式文件時,需要使用 Run。 例如,在下列標記 (Markup) 中,第一個 Paragraph 明確指定 Run 項目,而第二個則未明確指定。 兩個段落會產生相同的輸出。

<Paragraph>
  <Run>Paragraph that explicitly uses the Run element.</Run>
</Paragraph>

<Paragraph>
  This Paragraph omits the the Run element in markup. It renders
  the same as a Paragraph with Run used explicitly. 
</Paragraph>

**注意:**從 .NET Framework 4 開始,Run 物件的 Text 屬性為相依性屬性。 您可以將 Text 屬性繫結至資料來源,如 TextBlockText 屬性完全支援單向繫結。 Text 屬性也支援雙向繫結,但 RichTextBox 除外。 如需範例,請參閱 Run.Text

Span

Span 會將其他 Inline 內容項目分組在一起。 Span 項目本身沒有內建轉譯可套用至所涵蓋的內容。 不過,繼承自 Span 的項目,包括 HyperlinkBoldItalicUnderline,確實會將格式套用至文字。

以下是對內嵌 (Inline) 內容使用 Span 的範例,這段內容包含文字、Bold 項目及 Button 控制項。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">

  <Paragraph>
    Text before the Span. <Span Background="Red">Text within the Span is
    red 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. For
    example, it can contain a 
    <InlineUIContainer>
      <Button>Button</Button>
    </InlineUIContainer>
    or other UIElement, a Floater, a Figure, etc.</Span>
  </Paragraph>

</FlowDocument>

下列螢幕擷取畫面顯示這個範例呈現的效果。

螢幕擷取畫面:呈現的 Span 範例

InlineUIContainer

InlineUIContainer 可讓 UIElement 項目 (也就是 像 Button 的控制項) 內嵌於 Inline 內容項目中。 這個項目是上述 BlockUIContainer 的內嵌 (Inline) 對等項目。 以下的範例會使用 InlineUIContainerButton 內嵌插入至 Paragraph

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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>

Imports System
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class InlineUIContainerExample
        Inherits Page
        Public Sub New()
            Dim run1 As New Run(" Text to precede the button... ")
            Dim run2 As New Run(" Text to follow the button... ")

            ' Create a new button to be hosted in the paragraph.
            Dim myButton As New Button()
            myButton.Content = "Click me!"

            ' Create a new InlineUIContainer to contain the Button.
            Dim myInlineUIContainer As 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.
            Dim myParagraph As New Paragraph()
            myParagraph.Inlines.Add(run1)
            myParagraph.Inlines.Add(myInlineUIContainer)
            myParagraph.Inlines.Add(run2)

            ' Create a FlowDocument and add the paragraph to it.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(myParagraph)

            Me.Content = myFlowDocument
        End Sub
    End Class
End Namespace
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;
        }
    }
}

注意:在標記 (Markup) 中不需要明確使用 InlineUIContainer。 如果省略它,編譯程式碼時還是會建立 InlineUIContainer

Figure 和 Floater

FigureFloater 可用來以置放屬性的方式,將內容內嵌在非固定格式文件中,而置放屬性可以另外自訂,不受主要內容行文影響。 FigureFloater 項目通常用來反白顯示或強調部分內容、裝載支援影像或主要內容流程內的其他內容,或零散地注入相關內容 (如廣告)。

下列範例顯示如何將 Figure 內嵌至文字的段落。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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 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.
  </Paragraph>

</FlowDocument>

Imports System
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Controls
Imports System.Windows.Documents

Namespace SDKSample
    Partial Public Class FigureExample
        Inherits Page
        Public Sub New()

            ' Create strings to use as content.
            Dim strFigure As String = "A Figure embeds content into flow content with" & " placement properties that can be customized" & " independently from the primary content flow"
            Dim strOther As String = "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.
            Dim myFigure As New Figure()
            myFigure.Width = New FigureLength(300)
            myFigure.Height = New FigureLength(100)
            myFigure.Background = Brushes.GhostWhite
            myFigure.HorizontalAnchor = FigureHorizontalAnchor.PageLeft
            Dim myFigureParagraph As 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.
            Dim myParagraph As New Paragraph()
            myParagraph.Inlines.Add(myFigure)
            myParagraph.Inlines.Add(New Run(strOther))

            ' Create a FlowDocument and add the paragraph to it.
            Dim myFlowDocument As New FlowDocument()
            myFlowDocument.Blocks.Add(myParagraph)

            Me.Content = myFlowDocument
        End Sub
    End Class
End Namespace
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 範例

FigureFloater 在幾個方面有所不同,而且適用於不同的情況。

Figure:

  • 可以定位:您可以設定其水平與垂直錨點,以相對於頁面、內容、欄或段落的方式加以定位。 您也可以使用其 HorizontalOffsetVerticalOffset 屬性來指定任意位移。

  • 大小可以調整到超過一欄:您可以將 Figure 高度及寬度設定為頁面、內容或欄高度或寬度的倍數。 請注意,在頁面及內容的情況中,不容許大於 1 的倍數。 例如,您可以將 Figure 的寬度設定為「0.5 頁」或「0.25 內容」或「2 欄」。 也可以將高度與寬度設定為絕對像素值。

  • 不要分頁:如果 Figure 內的內容無法完全放入 Figure 中,則它將視大小呈現足夠的內容,而剩餘的內容則將遺失。

Floater:

  • 無法定位,而且將呈現任何可供其使用的空間。 您無法設定位移或錨定 Floater

  • 大小無法調整到超過一欄:Floater 預設為在一欄中調整大小。 它有個可以設為絕對像素值的 Width 屬性,但是如果此值大於一欄的寬度,則會忽略它,而且浮動器會在一欄中調整大小。 您可以設定正確的像素值寬度,將它設為小於一個資料行,但是調整大小與資料行無關,所以「0.5 資料行」不是 Floater 寬度的有效表示法。 Floater 沒有高度特性,且無法設定其高度,其高度根據內容而定

  • Floater 分頁:如果位在指定之寬度的內容超過一欄的高度,則浮動器會中斷並分頁至下一欄、下一頁等。

如果您想要控制大小及定位,而且有信心內容將完全放入指定的大小,則 Figure 是放置獨立內容的好位置。 Floater 是放置更多自由流動內容的好位置,這種內容的流動與主要頁面內容的流動相似,但與它隔開。

LineBreak

LineBreak 會使非固定格式內容中發生分行。 以下範例將說明 LineBreak 的用法。

<FlowDocument xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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>

下列螢幕擷取畫面顯示這個範例呈現的效果。

螢幕擷取畫面:LineBreak 範例

非固定格式集合項目

在上述的許多範例中,BlockCollectionInlineCollection 是用來以程式設計方式建構非固定格式內容。 例如,若要將項目加入至 Paragraph,您可以使用下列語法:

myParagraph.Inlines.Add(new Run("Some text"));

這會將 Run 加入至 ParagraphInlineCollection。 這與在標記 (Markup) 中的 Paragraph 內找到的隱含 Run 相同:

<Paragraph>

Some Text

</Paragraph>

下列範例是使用 BlockCollection 的範例,它會建立新的 Section,然後使用 Add 方法將新的 Paragraph 加入至 Section 內容。

            Dim secx As New Section()
            secx.Blocks.Add(New Paragraph(New Run("A bit of text content...")))
Section secx = new Section();
secx.Blocks.Add(new Paragraph(new Run("A bit of text content...")));

除了將項目加入至非固定格式集合以外,您也可以移除項目。 下列範例會刪除 Span 中的最後一個 Inline 項目。

            spanx.Inlines.Remove(spanx.Inlines.LastInline)
spanx.Inlines.Remove(spanx.Inlines.LastInline);

下列範例會清除 Span 的所有內容 (Inline 項目)。

            spanx.Inlines.Clear()
spanx.Inlines.Clear();

以程式設計方式使用非固定格式內容時,您通常會廣泛使用這些集合。

非固定格式項目是使用 InlineCollection (Inline) 還是 BlockCollection (Block) 包含其子項目,取決於父代可以包含的子項目型別 (BlockInline)。 非固定格式內容項目的內含規則在下一節的內容結構描述中會有摘要說明。

注意:與非固定格式內容搭配使用的還有第三種集合,即 ListItemCollection,但是這種集合只能與 List 搭配使用。 此外,有數種集合可以與 Table 搭配使用。 如需詳細資訊,請參閱資料表概觀

內容結構描述

有這麼多種不同的非固定格式內容項目,要追蹤項目可以包含的子項目型別,實在很累人。 下圖摘要指出非固定格式項目的內含規則。 箭頭代表可能的父代/子系關係。

圖表:非固定格式內容內含項目結構描述

如同上圖所示,項目能夠具有的子系不一定跟它是 Block 項目還是 Inline 項目有關。 例如,Span (Inline 項目) 只能具有 Inline 子項目,而 Figure (也是 Inline 項目) 只能具有 Block 子項目。 因此,這張圖表有助於快速判斷某個項目是否可以包含其他項目。 例如,我們將用圖表決定如何建構 RichTextBox 的非固定格式內容。

1.RichTextBox 必須包含 FlowDocument,而後者必須包含 Block 的衍生物件。 以下是上圖中的對應區段。

圖表:RichTextBox 內含項目規則

因此,標記 (Markup) 的外觀可能如下。

<RichTextBox>
  <FlowDocument>
    <!-- One or more Block-derived object… -->
  </FlowDocument>
</RichTextBox>

**2.**根據圖表,有數種 Block 項目可供選擇,包括 ParagraphSectionTableListBlockUIContainer (請參閱上述的 Block 衍生類別)。 假設我們要用 Table。 根據上圖,Table 包含 TableRowGroup,TableRowGroup 包含 TableRow 項目,TableRow 包含 TableCell 項目,而 TableCell 包含 Block 衍生物件。 以下是取自於上圖之 Table 的對應區段。

圖表:Table 的父代/子系結構描述

以下是對應標記 (Markup)。

<RichTextBox>
  <FlowDocument>
    <Table>
      <TableRowGroup>
        <TableRow>
          <TableCell>
            <!-- One or more Block-derived object… -->
          </TableCell>
        </TableRow>
      </TableRowGroup>
    </Table>
  </FlowDocument>
</RichTextBox>

**3.**同樣地,TableCell 下必須要有一個或多個 Block 項目。 為將其簡化,我們將在儲存格中加入一些文字。 我們可以使用 ParagraphRun 項目來執行這個動作。 以下是圖表中的對應區段,其中顯示 Paragraph 可包含 Inline 項目,而 Run (Inline 項目) 只能包含純文字。

圖表:Paragraph 的父代/子系結構描述圖表:Run 的父代/子系結構描述

以下是標記 (Markup) 的完整範例。

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <RichTextBox>
    <FlowDocument>

      <!-- Normally a table would have multiple rows and multiple
           cells but this code is for demonstration purposes.-->
      <Table>
        <TableRowGroup>
          <TableRow>
            <TableCell>
              <Paragraph>

                <!-- The schema does not actually require
                     explicit 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>

自訂文字

通常文字是非固定格式文件中最普遍的內容類型。 雖然以上介紹的物件可以用來控制大部分文字呈現的方式,但是還有其他方法可以自訂文字,本節稍後會做說明。

文字裝飾

文字裝飾讓您可以將底線、頂線、基準線及刪除線效果套用至文字 (請見下圖)。 這些裝飾是用 TextDecorations 屬性加入的,數個物件 (包括 InlineParagraphTextBlockTextBox) 都會公開這個屬性。

下列範例顯示如何設定 ParagraphTextDecorations 屬性。

<FlowDocument ColumnWidth="200">
  <Paragraph TextDecorations="Strikethrough">
    This text will render with the strikethrough effect.
  </Paragraph>
</FlowDocument>
                Dim parx As New Paragraph(New Run("This text will render with the strikethrough effect."))
                parx.TextDecorations = TextDecorations.Strikethrough
Paragraph parx = new Paragraph(new Run("This text will render with the strikethrough effect."));
parx.TextDecorations = TextDecorations.Strikethrough;

下圖顯示這個範例呈現的效果。

螢幕擷取畫面:套用預設刪除線效果的文字

下列各圖分別顯示「頂線」、「基線」及「底線」裝飾呈現的效果。

螢幕擷取畫面:頂線 TextDecorator螢幕擷取畫面:對文字套用的預設基準線效果螢幕擷取畫面:套用預設底線效果的文字

印刷樣式

大多數與非固定格式相關的屬性 (包括 TextElementFlowDocumentTextBlockTextBox) 都會公開 Typography 屬性。 這個屬性是用來控制文字的印刷樣式特性/種類 (例如 大小寫、上標和下標等)。

下列範例以 Paragraph 為例,顯示如何設定 Typography 屬性。

<Paragraph
  TextAlignment="Left"
  FontSize="18" 
  FontFamily="Palatino Linotype"
  Typography.NumeralStyle="OldStyle"
  Typography.Fraction="Stacked"
  Typography.Variants="Inferior"
>
  <Run>
    This text has some altered typography characteristics.  Note
    that use of an open type font is necessary for most typographic
    properties 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 屬性。

            Dim par As New Paragraph()

            Dim runText As New Run("This text has some altered typography characteristics.  Note" & "that use of an open type font is necessary for most typographic" & "properties to be effective.")
            Dim runNumerals As New Run("0123456789 10 11 12 13")
            Dim runFractions As New Run("1/2 2/3 3/4")

            par.Inlines.Add(runText)
            par.Inlines.Add(New LineBreak())
            par.Inlines.Add(New LineBreak())
            par.Inlines.Add(runNumerals)
            par.Inlines.Add(New LineBreak())
            par.Inlines.Add(New LineBreak())
            par.Inlines.Add(runFractions)

            par.TextAlignment = TextAlignment.Left
            par.FontSize = 18
            par.FontFamily = New FontFamily("Palatino Linotype")

            par.Typography.NumeralStyle = FontNumeralStyle.OldStyle
            par.Typography.Fraction = FontFraction.Stacked
            par.Typography.Variants = FontVariants.Inferior
Paragraph par = new Paragraph();

Run runText = new Run(
    "This text has some altered typography characteristics.  Note" +
    "that use of an open type font is necessary for most typographic" +
    "properties to be effective.");
Run runNumerals = new Run("0123456789 10 11 12 13");
Run runFractions = new Run("1/2 2/3 3/4");

par.Inlines.Add(runText);
par.Inlines.Add(new LineBreak());
par.Inlines.Add(new LineBreak());
par.Inlines.Add(runNumerals);
par.Inlines.Add(new LineBreak());
par.Inlines.Add(new LineBreak());
par.Inlines.Add(runFractions);

par.TextAlignment = TextAlignment.Left;
par.FontSize = 18;
par.FontFamily = new FontFamily("Palatino Linotype");

par.Typography.NumeralStyle = FontNumeralStyle.OldStyle;
par.Typography.Fraction = FontFraction.Stacked;
par.Typography.Variants = FontVariants.Inferior;

如需印刷樣式的詳細資訊,請參閱 WPF 中的印刷樣式

請參閱

概念

最佳化效能:文字

WPF 中的印刷樣式

TextElement 內容模型概觀

RichTextBox 概觀

WPF 中的文件

資料表概觀

附註概觀

其他資源

非固定格式內容項目 HOW TO 主題