表概述

Table 是一个块级元素,支持对流文档内容的基于网格的表示形式。 此元素极具灵活性,因此很有用,但也因此显得更加复杂,从而不容易理解和正确使用。

本主题包含以下各节:

表基础

表与网格有什么区别?

TableGrid 有一些共同的功能,但每个都有其各自最适合的场景。 Table 设计为在流内容内使用(有关流内容的详细信息,请参阅流文档概述)。 网格最适合在表单内(主要在流内容以外的任意位置)使用。 在 FlowDocument 中,Table 支持分页、列重排和内容选择等流内容行为,而 Grid 不支持。 另一方面,Grid 最适合在 FlowDocument 之外使用,其原因有多种,例如 Grid 基于行和列索引添加元素,而 Table 不是。 Grid 元素支持对子内容进行分层,从而允许多个元素共存于单个“单元格”内,而 Table 不支持分层。 Grid 的子元素可相对于其“单元格”边界区域进行绝对定位。 Table 不支持此功能。 最后,Grid 所需的资源比 Table 更少,因此请考虑使用 Grid 来提高性能。

基本表结构

Table 提供了一个基于网格的表示,其中包含列(由 TableColumn 元素表示)和行(由 TableRow 元素表示)。 TableColumn 元素不承载内容,只是定义列和列的特征。 TableRow 元素必须包含在 TableRowGroup 元素中,后者定义表的一组行。 TableCell 元素(包含表格要呈现的实际内容)必须包含在 TableRow 元素中。 TableCell 只能包含派生自 Block 的元素。 包括 TableCell 的有效子元素。

注意

TableCell 元素不可直接承载文本内容。 有关流内容元素(例如 TableCell)的包含规则的详细信息,请参阅流文档概述

注意

Table 类似于 Grid 元素,但具有更多功能,因此所需的资源会更多。

以下示例使用 XAML 定义一个简单的 2 行 3 列的表。

<!-- 
  Table is a Block element, and as such must be hosted in a container
  for Block elements.  FlowDocument provides such a container. 
-->
<FlowDocument>
  <Table>
    <!-- 
      This table has 3 columns, each described by a TableColumn 
      element nested in a Table.Columns collection element. 
    -->
    <Table.Columns>
      <TableColumn />
      <TableColumn />
      <TableColumn />
    </Table.Columns>
    <!-- 
      This table includes a single TableRowGroup which hosts 2 rows,
      each described by a TableRow element.
    -->
    <TableRowGroup>
      <!--
        Each of the 2 TableRow elements hosts 3 cells, described by
        TableCell elements.
      -->
      <TableRow>
        <TableCell>
          <!-- 
            TableCell elements may only host elements derived from Block.
            In this example, Paragaph elements serve as the ultimate content
            containers for the cells in this table.
          -->
          <Paragraph>Cell at Row 1 Column 1</Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>Cell at Row 1 Column 2</Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>Cell at Row 1 Column 3</Paragraph>
        </TableCell>
      </TableRow>
      <TableRow>
        <TableCell>
          <Paragraph>Cell at Row 2 Column 1</Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>Cell at Row 2 Column 2</Paragraph>
        </TableCell>
        <TableCell>
          <Paragraph>Cell at Row 2 Column 3</Paragraph>
        </TableCell>
      </TableRow>
    </TableRowGroup>
  </Table>
</FlowDocument>

下图显示了此示例的呈现效果。

Screenshot that shows how a basic table renders.

表包含

Table 派生自 Block 元素,并遵守 Block 级别元素的通用规则。 Table 元素可包含在以下任意元素中:

行分组

TableRowGroup 元素提供一种对表中的行进行任意分组的方式;表中的每行必须属于一个行分组。 行分组中的行通常具有相同的用途,并可作为一个组来设置样式。 行分组的一个常见使用方式是用于将特定用途的行(如标题行、标头和页脚行)与表中所含的主内容分隔开来。

以下示例使用 XAML 定义具有带样式的标头行和页脚行的表。

<Table>
  <Table.Resources>
    <!-- Style for header/footer rows. -->
    <Style x:Key="headerFooterRowStyle" TargetType="{x:Type TableRowGroup}">
      <Setter Property="FontWeight" Value="DemiBold"/>
      <Setter Property="FontSize" Value="16"/>
      <Setter Property="Background" Value="LightGray"/>
    </Style>

    <!-- Style for data rows. -->
    <Style x:Key="dataRowStyle" TargetType="{x:Type TableRowGroup}">
      <Setter Property="FontSize" Value="12"/>
      <Setter Property="FontStyle" Value="Italic"/>
    </Style>
  </Table.Resources>
  
  <Table.Columns>
    <TableColumn/> <TableColumn/> <TableColumn/> <TableColumn/>
  </Table.Columns>

  <!-- This TableRowGroup hosts a header row for the table. -->
  <TableRowGroup Style="{StaticResource headerFooterRowStyle}">
    <TableRow>
      <TableCell/>
      <TableCell><Paragraph>Gizmos</Paragraph></TableCell>
      <TableCell><Paragraph>Thingamajigs</Paragraph></TableCell>
      <TableCell><Paragraph>Doohickies</Paragraph></TableCell>
    </TableRow>
  </TableRowGroup>
  
  <!-- This TableRowGroup hosts the main data rows for the table. -->
  <TableRowGroup Style="{StaticResource dataRowStyle}">
    <TableRow>
      <TableCell><Paragraph Foreground="Blue">Blue</Paragraph></TableCell>
      <TableCell><Paragraph>1</Paragraph></TableCell>
      <TableCell><Paragraph>2</Paragraph></TableCell>
      <TableCell><Paragraph>3</Paragraph> </TableCell>
    </TableRow>
    <TableRow>
      <TableCell><Paragraph Foreground="Red">Red</Paragraph></TableCell>
      <TableCell><Paragraph>1</Paragraph></TableCell>
      <TableCell><Paragraph>2</Paragraph></TableCell>
      <TableCell><Paragraph>3</Paragraph></TableCell>
    </TableRow>
    <TableRow>
      <TableCell><Paragraph Foreground="Green">Green</Paragraph></TableCell>
      <TableCell><Paragraph>1</Paragraph></TableCell>
      <TableCell><Paragraph>2</Paragraph></TableCell>
      <TableCell><Paragraph>3</Paragraph></TableCell>
    </TableRow>
  </TableRowGroup>

  <!-- This TableRowGroup hosts a footer row for the table. -->
  <TableRowGroup Style="{StaticResource headerFooterRowStyle}">
    <TableRow>
      <TableCell><Paragraph>Totals</Paragraph></TableCell>
      <TableCell><Paragraph>3</Paragraph></TableCell>
      <TableCell><Paragraph>6</Paragraph></TableCell>
      <TableCell>
        <Table></Table>
      </TableCell>
    </TableRow>
  </TableRowGroup>
</Table>

下图显示了此示例的呈现效果。

Screenshot: Table row groups

背景呈现优先级

表元素以下列顺序呈现(按 Z 顺序从最低到最高排列)。 此顺序不能更改。 例如,对于这些元素,没有可用于替换此已有顺序的“Z 顺序”属性。

  1. Table

  2. TableColumn

  3. TableRowGroup

  4. TableRow

  5. TableCell

请参考以下示例,该示例对表内每个元素的背景色进行定义。

<Table Background="Yellow">
  <Table.Columns>
    <TableColumn/>
    <TableColumn Background="LightGreen"/>
    <TableColumn/>
  </Table.Columns>
  <TableRowGroup>
    <TableRow>
      <TableCell/><TableCell/><TableCell/>
    </TableRow>
  </TableRowGroup>
  <TableRowGroup Background="Tan">
    <TableRow>
      <TableCell/><TableCell/><TableCell/>
    </TableRow>
    <TableRow Background="LightBlue">
      <TableCell/><TableCell Background="Purple"/><TableCell/>
    </TableRow>
    <TableRow>
      <TableCell/><TableCell/><TableCell/>
    </TableRow>
  </TableRowGroup>
  <TableRowGroup>
    <TableRow>
      <TableCell/><TableCell/><TableCell/>
    </TableRow>
  </TableRowGroup>
</Table>

下图显示了此示例的呈现方式(仅显示背景色)。

Screenshot: Table z-order

跨行或列

通过分别使用 RowSpanColumnSpan 属性,可以将表格单元格配置为跨越多行或多列。

请参考以下示例,该示例中有一个跨三列的单元格。

<Table>
  <Table.Columns>
    <TableColumn/>
    <TableColumn/>
    <TableColumn/>
  </Table.Columns>

  <TableRowGroup>
    <TableRow>
      <TableCell ColumnSpan="3" Background="Cyan">
        <Paragraph>This cell spans all three columns.</Paragraph>
      </TableCell>
    </TableRow>
    <TableRow>
      <TableCell Background="LightGray"><Paragraph>Cell 1</Paragraph></TableCell>
      <TableCell Background="LightGray"><Paragraph>Cell 2</Paragraph></TableCell>
      <TableCell Background="LightGray"><Paragraph>Cell 3</Paragraph></TableCell>
    </TableRow>
  </TableRowGroup>
</Table>

下图显示了此示例的呈现效果。

Screenshot: Cell spanning all three columns

使用代码生成表

以下示例演示如何以编程方式创建 Table 并填充内容。 表格内容分为五行(由 RowGroups 对象中包含的 TableRow 对象表示)和六列(由 TableColumn 对象表示)。 各行用于不同的显示目的,其中,标题行用于显示整个表的标题,标头行用于描述表中的数据列,而页脚行则包含摘要信息。 请注意,“标题”行、“标头”行和“页脚”行并非表格所固有的,它们只是具有不同特征的行。 表单元格包含实际内容,可以包含文本、图像或几乎任何其他用户界面 (UI) 元素。

首先,创建一个 FlowDocument 来承载 Table,然后创建一个新的 Table 并将其添加到 FlowDocument 的内容中。

// Create the parent FlowDocument...
flowDoc = new FlowDocument();

// Create the Table...
table1 = new Table();
// ...and add it to the FlowDocument Blocks collection.
flowDoc.Blocks.Add(table1);

// Set some global formatting properties for the table.
table1.CellSpacing = 10;
table1.Background = Brushes.White;
' Create the parent FlowDocument...
flowDoc = New FlowDocument()

' Create the Table...
table1 = New Table()

' ...and add it to the FlowDocument Blocks collection.
flowDoc.Blocks.Add(table1)


' Set some global formatting properties for the table.
table1.CellSpacing = 10
table1.Background = Brushes.White

接下来,创建六个 TableColumn 对象并将其添加到表的 Columns 集合中,然后应用一些格式。

注意

请注意,表格的 Columns 集合使用标准的从零开始的索引。

// Create 6 columns and add them to the table's Columns collection.
int numberOfColumns = 6;
for (int x = 0; x < numberOfColumns; x++)
{
    table1.Columns.Add(new TableColumn());

    // Set alternating background colors for the middle colums.
    if(x%2 == 0)
        table1.Columns[x].Background = Brushes.Beige;
    else
        table1.Columns[x].Background = Brushes.LightSteelBlue;
}

' Create 6 columns and add them to the table's Columns collection.
Dim numberOfColumns = 6
Dim x
For x = 0 To numberOfColumns
    table1.Columns.Add(new TableColumn())

    ' Set alternating background colors for the middle colums.
    If x Mod 2 = 0 Then
        table1.Columns(x).Background = Brushes.Beige
    Else
        table1.Columns(x).Background = Brushes.LightSteelBlue
    End If
Next x

接下来,创建一个标题行,并将其添加到表中,同时应用某些格式设置。 标题行包含一个单元格,该单元格跨表中的全部六列。

// Create and add an empty TableRowGroup to hold the table's Rows.
table1.RowGroups.Add(new TableRowGroup());

// Add the first (title) row.
table1.RowGroups[0].Rows.Add(new TableRow());

// Alias the current working row for easy reference.
TableRow currentRow = table1.RowGroups[0].Rows[0];

// Global formatting for the title row.
currentRow.Background = Brushes.Silver;
currentRow.FontSize = 40;
currentRow.FontWeight = System.Windows.FontWeights.Bold;

// Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("2004 Sales Project"))));
// and set the row to span all 6 columns.
currentRow.Cells[0].ColumnSpan = 6;
' Create and add an empty TableRowGroup to hold the table's Rows.
table1.RowGroups.Add(new TableRowGroup())

' Add the first (title) row.
table1.RowGroups(0).Rows.Add(new TableRow())

' Alias the current working row for easy reference.
Dim currentRow As New TableRow()
currentRow = table1.RowGroups(0).Rows(0)

' Global formatting for the title row.
currentRow.Background = Brushes.Silver
currentRow.FontSize = 40
currentRow.FontWeight = System.Windows.FontWeights.Bold

' Add the header row with content, 
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("2004 Sales Project"))))
' and set the row to span all 6 columns.
currentRow.Cells(0).ColumnSpan = 6

接下来,创建一个标头行并将其添加到表中,同时创建标头行中的单元格并填充其内容。

// Add the second (header) row.
table1.RowGroups[0].Rows.Add(new TableRow());
currentRow = table1.RowGroups[0].Rows[1];

// Global formatting for the header row.
currentRow.FontSize = 18;
currentRow.FontWeight = FontWeights.Bold;

// Add cells with content to the second row.
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Product"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 1"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 2"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 3"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 4"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("TOTAL"))));
' Add the second (header) row.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(1)

' Global formatting for the header row.
currentRow.FontSize = 18
currentRow.FontWeight = FontWeights.Bold

' Add cells with content to the second row.
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Product"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 1"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 2"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 3"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Quarter 4"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("TOTAL"))))

接下来,创建一个数据行并将其添加到表中,同时创建此行中的单元格并填充其内容。 生成此行的过程与生成标头行的过程类似,只是应用的格式设置略有不同。

// Add the third row.
table1.RowGroups[0].Rows.Add(new TableRow());
currentRow = table1.RowGroups[0].Rows[2];

// Global formatting for the row.
currentRow.FontSize = 12;
currentRow.FontWeight = FontWeights.Normal;

// Add cells with content to the third row.
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Widgets"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$50,000"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$55,000"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$60,000"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$65,000"))));
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$230,000"))));

// Bold the first cell.
currentRow.Cells[0].FontWeight = FontWeights.Bold;
' Add the third row.
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(2)

' Global formatting for the row.
currentRow.FontSize = 12
currentRow.FontWeight = FontWeights.Normal

' Add cells with content to the third row.
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Widgets"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$50,000"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$55,000"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$60,000"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$65,000"))))
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("$230,000"))))

' Bold the first cell.
currentRow.Cells(0).FontWeight = FontWeights.Bold

最后,创建、添加脚注行并设置其格式。 与标题行类似,脚注包含的单元格的跨度为表中的全部六列。

table1.RowGroups[0].Rows.Add(new TableRow());
currentRow = table1.RowGroups[0].Rows[3];

// Global formatting for the footer row.
currentRow.Background = Brushes.LightGray;
currentRow.FontSize = 18;
currentRow.FontWeight = System.Windows.FontWeights.Normal;

// Add the header row with content,
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Projected 2004 Revenue: $810,000"))));
// and set the row to span all 6 columns.
currentRow.Cells[0].ColumnSpan = 6;
table1.RowGroups(0).Rows.Add(new TableRow())
currentRow = table1.RowGroups(0).Rows(3)

' Global formatting for the footer row.
currentRow.Background = Brushes.LightGray
currentRow.FontSize = 18
currentRow.FontWeight = System.Windows.FontWeights.Normal

' Add the header row with content, 
currentRow.Cells.Add(new TableCell(new Paragraph(new Run("Projected 2004 Revenue: $810,000"))))
' and set the row to span all 6 columns.
currentRow.Cells(0).ColumnSpan = 6

另请参阅