Cenni preliminari sull'elemento Table

Table è un elemento a livello di blocco che supporta la presentazione basata su griglia del contenuto di documenti dinamici. La flessibilità di questo elemento lo rende molto utile, ma al contempo ne complica la comprensione e l'utilizzo corretto.

Di seguito sono elencate le diverse sezioni di questo argomento.

  • Introduzione all'elemento Table

  • Differenze tra l'elemento Table e l'elemento Grid

  • Struttura di base dell'elemento Table

  • Contenuto dell'elemento Table

  • Raggruppamenti di righe

  • Precedenza del rendering dello sfondo

  • Estensione su più righe o colonne

  • Compilazione di un elemento Table con codice

  • Argomenti correlati

Introduzione all'elemento Table

Differenze tra l'elemento Table e l'elemento Grid

Gli elementi Table e Grid condividono alcune funzionalità comuni, ma ciascuno di essi si rivela adatto a scenari diversi. Un elemento Table è progettato per l'utilizzo all'interno del contenuto di flusso (per ulteriori informazioni sul contenuto di flusso, vedere Cenni preliminari sui documenti dinamici). Gli elementi Grid vengono utilizzati con maggior efficacia all'interno di form (in generale all'esterno del contenuto di flusso). All'interno di un oggetto FlowDocument, un elemento Table supporta comportamenti del contenuto di flusso come impaginazione, riflusso di colonne e selezione di contenuto, a differenza di un elemento Grid. Un elemento Grid viene invece utilizzato con maggior efficacia all'esterno di un oggetto FlowDocument per diversi motivi, incluso il fatto che l'elemento Grid aggiunge gli elementi in base a un indice di riga e di colonna, a differenza di Table. L'elemento Grid consente la sovrapposizione di contenuti figlio, permettendo la presenza di più di un elemento all'interno di un'unica "cella". L'elemento Table non supporta la sovrapposizione. Gli elementi figlio di un elemento Grid possono essere posizionati in modo assoluto rispetto all'area della relativa "cella". Table non supporta questa funzionalità. Infine, poiché un elemento Grid richiede un numero inferiore di risorse rispetto a Table, è opportuno considerare l'utilizzo di Grid per migliorare le prestazioni.

Struttura di base dell'elemento Table

L'elemento Table fornisce una presentazione basata su griglia costituita da colonne (rappresentate da elementi TableColumn) e righe (rappresentate da elementi TableRow). Gli elementi TableColumn non ospitano contenuto, ma definiscono semplicemente le colonne e le relative caratteristiche. Gli elementi TableRow devono essere ospitati in un elemento TableRowGroup che definisce un raggruppamento di righe per la tabella. Gli elementi TableCell, che contengono il contenuto effettivo presentato dalla tabella, devono essere ospitati in un elemento TableRow. TableCell può contenere solo elementi che derivano da Block. Tra gli elementi figlio validi per TableCell sono inclusi:

NotaNota

Gli elementi TableCell non possono ospitare direttamente contenuto di testo.Per ulteriori informazioni sulle regole di contenuto per gli elementi di contenuto dinamico come TableCell, vedere Cenni preliminari sui documenti dinamici.

NotaNota

Table è simile a Grid ma offre maggiori funzionalità e, pertanto, richiede un sovraccarico di risorse maggiore.

Nell'esempio riportato di seguito viene definita una semplice tabella 2 x 3 con XAML.

<!-- 
  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>

Nella figura riportata di seguito viene illustrato il rendering dell'esempio.

Schermata: rendering di una tabella semplice

Contenuto dell'elemento Table

Table deriva dall'elemento Block ed è conforme alle regole comuni per gli elementi a livello di Block. Un elemento Table può essere contenuto da ognuno degli elementi riportati di seguito:

Raggruppamenti di righe

L'elemento TableRowGroup consente di raggruppare in modo arbitrario le righe in una tabella, ciascuna delle quali deve appartenere a un raggruppamento di righe. Spesso, le righe appartenenti allo stesso gruppo condividono un intento comune ed è possibile utilizzare uno stile comune per il gruppo. Un utilizzo tipico dei raggruppamenti di righe consiste nel separare le righe finalizzate a scopi specifici, ad esempio le righe di titolo, intestazione e piè di pagina, dal contenuto principale della tabella.

Nell'esempio riportato di seguito viene utilizzato XAML per definire una tabella con righe di intestazione e piè di pagina personalizzate con stili.

<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>

Nella figura riportata di seguito viene illustrato il rendering dell'esempio.

Schermata: gruppi di righe di tabella

Precedenza del rendering dello sfondo

Il rendering di elementi Table viene eseguito nell'ordine seguente (ordine z dal più basso al più alto). Questo ordine non può essere modificato. Ad esempio, per questi elementi non esiste una proprietà "ordine Z" che è possibile utilizzare per l'override dell'ordine stabilito.

  1. Table

  2. TableColumn

  3. TableRowGroup

  4. TableRow

  5. TableCell

Nell'esempio riportato di seguito vengono definiti i colori di sfondo per ciascun elemento all'interno di una tabella.

<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>

Nella figura riportata di seguito viene illustrato il rendering dell'esempio (visualizzazione dei soli colori di sfondo).

Schermata: ordine Z della tabella

Estensione su più righe o colonne

Le celle della tabella possono essere configurate per estendersi su più righe o colonne utilizzando rispettivamente gli attributi RowSpan o ColumnSpan.

Nell'esempio riportato di seguito una cella si estende su tre colonne.

<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>

Nella figura riportata di seguito viene illustrato il rendering dell'esempio.

Schermata: cella che si estende su tutte e tre colonne

Compilazione di un elemento Table con codice

Negli esempi riportati di seguito viene illustrato come creare un elemento Table a livello di codice e inserirvi contenuto. Il contenuto della tabella è ripartito in cinque righe (rappresentate da oggetti TableRow contenuti in un oggetto RowGroups) e sei colonne (rappresentate da oggetti TableColumn). Le righe vengono utilizzate per scopi di presentazione diversi, ad esempio una riga è destinata a contenere il titolo dell'intera tabella, una riga di intestazione a descrivere le colonne di dati nella tabella e una riga di piè di pagina a fornire informazioni di riepilogo. Si noti che i concetti di righe del "titolo", "intestazione" e "piè di pagina" non sono inerenti la tabella, ma fanno semplicemente riferimento a righe con caratteristiche diverse. Le celle della tabella ospitano il contenuto effettivo, che può essere costituito da testo, immagini o qualsiasi altro elemento user interface (UI).

Viene innanzitutto creato un oggetto FlowDocument per ospitare l'elemento Table, quindi viene creato un nuovo elemento Table e aggiunto al contenuto di 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;

Successivamente, vengono creati sei oggetti TableColumn e aggiunti all'insieme Columns della tabella, con l'applicazione di alcuni elementi di formattazione.

NotaNota

Si noti che l'insieme Columns della tabella utilizza un'indicizzazione a base zero standard.

            ' 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 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;
            }

Viene quindi creata una riga del titolo e aggiunta alla tabella con l'applicazione di alcuni elementi di formattazione. La riga del titolo può contenere una sola cella che si estende su tutte e sei le colonne della tabella.

' 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
// 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;

Viene quindi creata e aggiunta alla tabella una riga di intestazione, per la quale vengono create celle in cui viene inserito contenuto.

' 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"))));

In seguito, viene creata e aggiunta alla tabella una riga per i dati, per la quale vengono create celle in cui viene inserito contenuto. La compilazione di questa riga è simile alla compilazione della riga di intestazione, con l'applicazione di una formattazione leggermente diversa.

' 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;

Infine, viene creata, aggiunta e formattata una riga a piè di pagina. Analogamente alla riga del titolo, il piè di pagina contiene una sola cella che si estende su tutte e sei colonne della tabella.

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;

Vedere anche

Attività

Procedura: definire un oggetto Table tramite XAML

Procedura: utilizzare elementi di contenuto dinamico

Concetti

Cenni preliminari sui documenti dinamici

Documenti in WPF