Condividi tramite


Panoramica del documento di Flow

I documenti di flusso sono progettati per ottimizzare la visualizzazione e la leggibilità. Invece di essere impostati su un layout predefinito, i documenti di flusso regolano dinamicamente e riorganizzano il contenuto in base a variabili di esecuzione, come le dimensioni della finestra, la risoluzione del dispositivo e le preferenze facoltative dell'utente. Inoltre, i documenti di flusso offrono funzionalità avanzate per i documenti, ad esempio la paginazione e le colonne. In questo argomento viene fornita una panoramica dei documenti di flusso e di come crearli.

Che cos'è un documento di flusso

Un documento di flusso è progettato per il "riadattamento del contenuto" a seconda delle dimensioni della finestra, della risoluzione del dispositivo e di altre variabili ambientali. Inoltre, i documenti di flusso hanno una serie di funzionalità predefinite, tra cui la ricerca, le modalità di visualizzazione che ottimizzano la leggibilità e la possibilità di modificare le dimensioni e l'aspetto dei tipi di carattere. I documenti di flusso vengono usati al meglio quando la facilità di lettura è lo scenario principale di utilizzo dei documenti. Al contrario, i documenti fissi sono progettati per avere una presentazione statica. I documenti fissi sono utili quando la fedeltà del contenuto di origine è essenziale. Per altre informazioni sui diversi tipi di documenti, vedere Documenti in WPF.

La figura seguente mostra un documento di flusso di esempio visualizzato in diverse finestre di dimensioni diverse. Man mano che l'area di visualizzazione cambia, il contenuto si adatta per sfruttare al meglio lo spazio disponibile.

flusso del contenuto del documento

Come illustrato nell'immagine precedente, il contenuto del flusso può includere molti componenti, tra cui paragrafi, elenchi, immagini e altro ancora. Questi componenti corrispondono agli elementi nel markup e negli oggetti nel codice procedurale. Queste classi verranno approfondite in dettaglio più avanti nella sezione dedicata alle classi correlate al flusso di questa panoramica. Per il momento, ecco un semplice esempio di codice che crea un documento di flusso costituito da un paragrafo con testo in grassetto e un elenco.

<!-- This simple flow document includes a paragraph with some
     bold 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 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;
        }
    }
}

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

La figura seguente mostra l'aspetto di questo frammento di codice.

screenshot : esempio di FlowDocument sottoposto a rendering

In questo esempio, il controllo FlowDocumentReader viene usato per ospitare il contenuto del flusso. Per ulteriori informazioni sui controlli di hosting del contenuto del flusso, vedere Tipi di documenti di flusso . Paragraph, List, ListIteme gli elementi Bold vengono usati per controllare la formattazione del contenuto, in base al relativo ordine nel markup. Ad esempio, l'elemento Bold si estende solo in parte del testo nel paragrafo; di conseguenza, solo quella parte del testo è in grassetto. Se è stato usato html, questo sarà familiare per te.

Come evidenziato nella figura precedente, sono disponibili diverse funzionalità integrate in Documenti di Flow:

  • Ricerca: consente all'utente di eseguire una ricerca full-text di un intero documento.

  • Modalità di visualizzazione: l'utente può selezionare la modalità di visualizzazione preferita, inclusa una modalità di visualizzazione a pagina singola (pagina alla volta), una modalità di visualizzazione a due pagine alla volta (formato lettura libro) e una modalità di visualizzazione scorrimento continuo (senza fondo). Per altre informazioni su queste modalità di visualizzazione, vedere FlowDocumentReaderViewingMode.

  • Controlli di spostamento pagina: se la modalità di visualizzazione del documento utilizza pagine, i controlli di spostamento della pagina includono un pulsante per passare alla pagina successiva (freccia giù) o alla pagina precedente (freccia su), nonché indicatori per il numero di pagina corrente e il numero totale di pagine. È anche possibile scorrere le pagine usando i tasti di direzione della tastiera.

  • Zoom: i controlli zoom consentono all'utente di aumentare o diminuire il livello di zoom facendo clic rispettivamente sui pulsanti più o meno. I controlli zoom includono anche un dispositivo di scorrimento per regolare il livello di zoom. Per altre informazioni, vedere Zoom.

Queste funzionalità possono essere modificate in base al controllo usato per ospitare il contenuto del flusso. Nella sezione successiva vengono descritti i diversi controlli.

Tipi di documento di flusso

La visualizzazione del contenuto di un documento di flusso e il modo in cui appare dipendono dall'oggetto utilizzato per ospitare tale contenuto. Sono disponibili quattro controlli che supportano la visualizzazione del contenuto del flusso: FlowDocumentReader, FlowDocumentPageViewer, RichTextBoxe FlowDocumentScrollViewer. Questi controlli sono descritti brevemente di seguito.

Nota

FlowDocument è necessario per ospitare direttamente i contenuti di flusso, quindi tutti questi controlli di visualizzazione utilizzano un FlowDocument per ospitarli.

FlowDocumentReader

FlowDocumentReader include funzionalità che consentono all'utente di scegliere dinamicamente tra diverse modalità di visualizzazione, tra cui una modalità di visualizzazione a pagina singola (pagina alla volta), una modalità di visualizzazione a due pagine alla volta (formato di lettura libro) e una modalità di visualizzazione continua di scorrimento (senza fondo). Per altre informazioni su queste modalità di visualizzazione, vedere FlowDocumentReaderViewingMode. Se non è necessaria la possibilità di passare dinamicamente tra diverse modalità di visualizzazione, FlowDocumentPageViewer e FlowDocumentScrollViewer forniscono dei visualizzatori di contenuto a flusso più leggeri che sono fissi in una particolare modalità di visualizzazione.

FlowDocumentPageViewer e FlowDocumentScrollViewer

FlowDocumentPageViewer mostra il contenuto in modalità di visualizzazione di pagina alla volta, mentre FlowDocumentScrollViewer mostra il contenuto in modalità di scorrimento continuo. Sia FlowDocumentPageViewer che FlowDocumentScrollViewer sono fissi in una particolare modalità di visualizzazione. Confronta FlowDocumentReader, che include funzionalità che consentono all'utente di scegliere in modo dinamico tra diverse modalità di visualizzazione (come previsto dall'enumerazione FlowDocumentReaderViewingMode), a costo di essere più dispendioso in termini di risorse rispetto a FlowDocumentPageViewer o FlowDocumentScrollViewer.

Per impostazione predefinita, viene sempre visualizzata una barra di scorrimento verticale e, se necessario, una barra di scorrimento orizzontale diventa visibile. L'interfaccia utente predefinita per FlowDocumentScrollViewer non include una barra degli strumenti; Tuttavia, la proprietà IsToolBarVisible può essere usata per abilitare una barra degli strumenti predefinita.

Casella di Testo Avanzata (RichTextBox)

Usare un RichTextBox quando si vuole consentire all'utente di modificare il contenuto del flusso. Ad esempio, se si vuole creare un editor che consenta a un utente di modificare elementi come tabelle, corsivo e formattazione in grassetto e così via, si userà un RichTextBox. Per altre informazioni, vedere Panoramica di RichTextBox.

Nota

Il contenuto del flusso all'interno di un RichTextBox non si comporta esattamente come quello contenuto in altri controlli. Ad esempio, non ci sono colonne in un RichTextBox e quindi non vi è alcun comportamento di ridimensionamento automatico. Inoltre, le funzionalità predefinite in genere di contenuto di flusso come la ricerca, la modalità di visualizzazione, lo spostamento di pagine e lo zoom non sono disponibili all'interno di un RichTextBox.

Creazione del contenuto del flusso

Il contenuto del flusso può essere complesso, costituito da vari elementi, tra cui testo, immagini, tabelle e persino UIElement classi derivate come i controlli. Per comprendere come creare contenuto di flusso complesso, i punti seguenti sono fondamentali:

  • classi correlate al flusso: ogni classe usata nel contenuto del flusso ha uno scopo specifico. Inoltre, la relazione gerarchica tra le classi di flusso consente di comprendere come vengono usate. Ad esempio, le classi derivate dalla classe Block vengono usate per contenere altri oggetti mentre le classi derivate da Inline contengono oggetti visualizzati.

  • Schema del contenuto: un documento di flusso può richiedere un numero considerevole di elementi annidati. Lo schema del contenuto specifica le possibili relazioni padre/figlio tra gli elementi.

Le sezioni seguenti verranno approfondite in modo più dettagliato su ognuna di queste aree.

Il diagramma seguente mostra gli oggetti più comunemente usati per il contenuto fluido.

diagramma : gerarchia di classi dell'elemento del contenuto di Flow

Ai fini del contenuto del flusso, esistono due categorie importanti:

  1. Classi derivate da blocchi: anche chiamate "Elementi contenuto di blocco" o semplicemente "Elementi di blocco". Gli elementi che ereditano da Block possono essere usati per raggruppare gli elementi in un elemento padre comune o per applicare attributi comuni a un gruppo.

  2. classi derivate inline: detti anche "elementi di contenuto inline" o semplicemente "elementi inline". Gli elementi che ereditano da Inline sono contenuti all'interno di un elemento Block o di un altro elemento inline. Gli elementi inline vengono spesso usati come contenitore diretto di contenuto di cui viene eseguito il rendering sullo schermo. Ad esempio, un Paragraph (elemento Block) può contenere un Run (elemento Inline), ma il Run contiene effettivamente il testo di cui viene eseguito il rendering sullo schermo.

Ogni classe in queste due categorie è descritta brevemente di seguito.

Classi derivate da blocchi

paragrafo

Paragraph viene in genere usato per raggruppare il contenuto in un paragrafo. L'uso più semplice e comune di Paragraph consiste nel creare un paragrafo di testo.

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

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

Tuttavia, è anche possibile contenere altri elementi derivati inline come si vedrà di seguito.

sezione

Section viene usato solo per contenere altri elementi derivati da Block. Non applica alcuna formattazione predefinita agli elementi contenuti. Tuttavia, tutti i valori delle proprietà impostati su un Section si applicano ai suoi elementi figlio. Una sezione consente inoltre di scorrere a livello di codice la sua raccolta di elementi figlio. Section viene usato in modo analogo al tag <DIV> in HTML.

Nell'esempio seguente vengono definiti tre paragrafi sotto un Section. La sezione ha un valore della proprietà Background rosso, pertanto anche il colore di sfondo dei paragrafi è rosso.

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

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

BlockUIContainer

BlockUIContainer consente di incorporare UIElement elementi (ad esempio un Button) nel contenuto del flusso derivato da blocchi. InlineUIContainer (vedere di seguito) viene usato per incorporare elementi UIElement nel flusso di contenuto derivato inline. BlockUIContainer e InlineUIContainer sono importanti perché non esiste un altro modo per usare un UIElement nel contenuto di flusso, a meno che non sia contenuto all'interno di uno di questi due elementi.

Nell'esempio seguente si illustra come usare l'elemento BlockUIContainer per ospitare oggetti UIElement all'interno del contenuto fluente.

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

La figura seguente mostra come viene eseguito il rendering di questo esempio:

Screenshot che mostra un UIElement incorporato nel contenuto del flusso.

Elenco

List viene utilizzato per creare un elenco puntato o numerico. Impostare la proprietà MarkerStyle su un valore di enumerazione TextMarkerStyle per determinare lo stile dell'elenco. L'esempio seguente illustra come creare un elenco semplice.

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

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

Nota

List è l'unico elemento di flusso che usa il ListItemCollection per gestire gli elementi figli.

tabella

Table viene usato per creare una tabella. Table è simile all'elemento Grid, ma ha più funzionalità e pertanto richiede un sovraccarico maggiore delle risorse. Poiché Grid è un UIElement, non può essere usato nel flusso di contenuti, a meno che non sia contenuto in un BlockUIContainer o InlineUIContainer. Per altre informazioni su Table, vedere Panoramica della tabella .

Classi derivate da inline

Eseguire

Run viene usato per contenere testo non formattato. Ci si potrebbe aspettare che gli oggetti Run vengano usati ampiamente nel contenuto di flusso. Tuttavia, nel markup, gli elementi Run non sono tenuti a essere usati in modo esplicito. Run deve essere usato durante la creazione o la modifica di documenti di flusso tramite codice. Nel markup seguente, ad esempio, il primo Paragraph specifica in modo esplicito l'elemento Run mentre il secondo non lo fa. Entrambi i paragrafi generano un output identico.

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

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

Nota

A partire da .NET Framework 4, la proprietà Text dell'oggetto Run è una proprietà di dipendenza. È possibile associare la proprietà Text a un'origine dati, ad esempio un TextBlock. La proprietà Text supporta pienamente il binding unidirezionale. La proprietà Text supporta anche l'associazione bidirezionale, ad eccezione di RichTextBox. Per un esempio, vedere Run.Text.

Intervallo

Span raggruppa altri elementi di contenuto inline. Nessun rendering intrinseco viene applicato al contenuto all'interno di un elemento Span. Tuttavia, gli elementi che ereditano da Span inclusi Hyperlink, Bold, Italic e Underline applicano la formattazione al testo.

Di seguito è riportato un esempio di un Span usato per contenere contenuto inline, tra cui testo, un elemento Bold e un 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 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>

Lo screenshot seguente mostra come viene eseguito il rendering di questo esempio.

Screenshot: esempio di intervallo sottoposto a rendering

InlineUIContainer

InlineUIContainer consente di incorporare elementi UIElement (ad esempio un controllo come Button) in un elemento Inline di contenuto. Questo elemento è l'equivalente inline a BlockUIContainer descritto in precedenza. Di seguito è riportato un esempio che usa InlineUIContainer per inserire un Button in linea in un 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;
        }
    }
}

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

Nota

InlineUIContainer non deve essere utilizzato esplicitamente nel markup. Se lo si omette, verrà comunque creato un InlineUIContainer al momento della compilazione del codice.

Figura e Galleggiante

Figure e Floater vengono usati per incorporare contenuto nei documenti di Flow con proprietà di posizionamento che possono essere personalizzate indipendentemente dal flusso di contenuto primario. Figure o Floater elementi vengono spesso usati per evidenziare o accentuare parti di contenuto, per ospitare immagini di supporto o altro contenuto all'interno del flusso di contenuto principale o per inserire contenuti liberamente correlati, ad esempio annunci pubblicitari.

Nell'esempio seguente viene illustrato come incorporare un Figure in un paragrafo di testo.

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

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

La figura seguente mostra come viene eseguito il rendering di questo esempio.

screenshot : esempio di figura

Figure e Floater differiscono in diversi modi e vengono usati per diversi scenari.

Figura :

  • Può essere posizionato: è possibile impostare gli ancoraggi orizzontali e verticali per ancorarlo rispetto alla pagina, al contenuto, alla colonna o al paragrafo. È anche possibile utilizzare le relative proprietà HorizontalOffset e VerticalOffset per specificare offset arbitrari.

  • È dimensionabile su più di una colonna: è possibile impostare l'altezza e la larghezza di Figure come multipli della pagina, del contenuto o dell'altezza o larghezza di una colonna. Si noti che nel caso della pagina e del contenuto, multipli maggiori di 1 non sono consentiti. Ad esempio, è possibile impostare la larghezza di un Figure su "0.5 page" o "0.25 content" o "2 Column". È anche possibile impostare altezza e larghezza su valori pixel assoluti.

  • Non impagina: se il contenuto all'interno di un Figure non rientra nell'Figure, eseguirà il rendering di qualsiasi contenuto adatto e il contenuto rimanente andrà perso

Galleggiante:

  • Non può essere posizionato e verrà visualizzato ovunque ci sia spazio disponibile. Non è possibile impostare l'offset o ancorare un Floater.

  • Impossibile ridimensionare a più di una colonna: per impostazione predefinita, Floater è dimensionato a una colonna. Ha una proprietà Width che può essere impostata su un valore assoluto in pixel, ma se questo valore è maggiore di una larghezza di colonna viene ignorato e il floater viene ridimensionato a una colonna. È possibile ridimensionarlo in meno di una colonna impostando la larghezza del pixel corretta, ma il ridimensionamento non è relativo alla colonna, quindi "0,5Column" non è un'espressione valida per Floater larghezza. Floater non ha alcuna proprietà height e la sua altezza non può essere impostata, dipende dal contenuto

  • Floater impagina: se il relativo contenuto alla larghezza specificata si estende più di un'altezza di colonna, floater viene interrotto e impaginato nella colonna successiva, nella pagina successiva e così via.

Figure è un buon posto per inserire contenuto autonomo in cui si desidera controllare le dimensioni e il posizionamento e assicurarsi che il contenuto si adatti alle dimensioni specificate. Floater è un buon posto per inserire contenuti a flusso più libero che scorrono in modo simile al contenuto della pagina principale, ma sono separati da esso.

LineBreak

LineBreak causa un'interruzione di riga nel flusso di contenuti. Nell'esempio seguente viene illustrato l'uso di 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>

Lo screenshot seguente mostra come viene eseguito il rendering di questo esempio.

Screenshot: esempio di interruzione di riga

Elementi della raccolta di flussi

In molti degli esempi precedenti, le BlockCollection e le InlineCollection vengono usate per costruire il contenuto del flusso a livello di codice. Ad esempio, per aggiungere elementi a un Paragraph, è possibile usare la sintassi :

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

In questo modo viene aggiunto un Run alla InlineCollection del Paragraph. Si tratta dello stesso Run implicito trovato all'interno di un Paragraph nel markup:

<Paragraph>
Some Text
</Paragraph>

Come esempio di utilizzo del , nell'esempio seguente viene creato un nuovo e quindi viene utilizzato il metodo add per aggiungere un nuovo al contenuto del .

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

Oltre ad aggiungere elementi a una raccolta di flussi, è possibile rimuovere anche gli elementi. Nell'esempio seguente viene eliminato l'ultimo elemento Inline nel Span.

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

Nell'esempio seguente vengono cancellati tutti i contenuti (Inline elementi) dal Span.

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

Quando si lavora con contenuti del flusso in modo programmatico, è probabile che si utilizzino ampiamente queste raccolte.

Se un elemento di flusso utilizza un InlineCollection (Inlines) o un BlockCollection (Blocks) per contenere i relativi elementi figlio dipende dal tipo di elementi figlio (Block o Inline) che possono essere contenuti dall'elemento padre. Le regole di contenimento per gli elementi del contenuto del flusso vengono riepilogate nello schema del contenuto nella sezione successiva.

Nota

Esiste un terzo tipo di raccolta usato con il contenuto di flusso, il ListItemCollection, ma la raccolta viene usata solo con un List. Inoltre, ci sono diverse raccolte utilizzate con Table. Per ulteriori informazioni, vedere la Panoramica della tabella .

Schema del contenuto

Dato il numero di diversi elementi di contenuto di flusso, può risultare complicato tenere traccia dei tipi di elementi figli che un elemento può contenere. Il diagramma seguente riepiloga le regole di contenimento per gli elementi di flusso. Le frecce rappresentano le possibili relazioni padre/figlio.

Diagramma : schema di contenimento del contenuto di flusso

Come si può notare nel diagramma precedente, gli elementi figlio consentiti per un elemento non sono necessariamente determinati dal fatto che si tratti di un elemento Block o di un elemento Inline. Ad esempio, un Span (un elemento Inline) può avere solo elementi figlio Inline mentre un Figure (anche un elemento Inline) può avere solo elementi figlio Block. Pertanto, un diagramma è utile per determinare rapidamente quale elemento può essere contenuto in un altro. Ad esempio, utilizziamo il diagramma per determinare come strutturare il contenuto del flusso di un RichTextBox.

1. Un RichTextBox deve contenere un FlowDocument che a sua volta deve contenere un oggetto derivato da Block. Di seguito è riportato il segmento corrispondente del diagramma precedente.

Diagramma : Regole di contenimento RichTextBox

Finora, questo è come potrebbe apparire il markup.

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

2. In base al diagramma sono disponibili diversi elementi Block tra cui Paragraph, Section, Table, Liste BlockUIContainer (vedere Classi derivate da blocchi sopra). Diciamo che vogliamo un Table. Secondo il diagramma precedente, un Table contiene un TableRowGroup che contiene elementi TableRow, che contengono elementi TableCell che contengono un oggetto derivato da Block. Di seguito è riportato il segmento corrispondente per Table tratto dal diagramma precedente.

diagramma: schema padre/figlio per la tabella

Di seguito è riportato il markup corrispondente.

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

3. Di nuovo, uno o più elementi Block sono necessari sotto un TableCell. Per semplificare, inserire del testo all'interno della cella. A tale scopo, è possibile usare un Paragraph con un elemento Run. Di seguito sono riportati i segmenti corrispondenti del diagramma che mostra che un Paragraph può accettare un elemento Inline e che un Run (un elemento Inline) può accettare solo testo normale.

Diagramma : schema padre/figlio per Paragrafo

Diagramma : schema padre/figlio per l'esecuzione di

Di seguito è riportato l'intero esempio nel markup.

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

Personalizzazione del testo

In genere il testo è il tipo di contenuto più diffuso in un documento di flusso. Anche se gli oggetti introdotti in precedenza possono essere usati per controllare la maggior parte degli aspetti del rendering del testo, esistono altri metodi per personalizzare il testo descritto in questa sezione.

Decorazioni di testo

Le decorazioni di testo consentono di applicare gli effetti sottolineatura, soprallineatura, misura e barrato al testo (vedere le immagini di seguito). Queste decorazioni vengono aggiunte utilizzando la proprietà TextDecorations esposta da numerosi oggetti, tra cui Inline, Paragraph, TextBlocke TextBox.

Nell'esempio seguente viene illustrato come impostare la proprietà TextDecorations di un 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;
Dim parx As New Paragraph(New Run("This text will render with the strikethrough effect."))
parx.TextDecorations = TextDecorations.Strikethrough

La figura seguente mostra come viene eseguito il rendering di questo esempio.

Screenshot: testo con effetto barrato predefinito

Le figure seguenti mostrano come vengono visualizzate rispettivamente le decorazioni Overline, Baselinee Underline.

Screenshot: TextDecorator Overline

Screenshot: effetto predefinito della linea di base sul testo

Screenshot: testo con effetto di sottolineatura predefinito

Tipografia

La proprietà Typography è esposta dalla maggior parte dei contenuti legati al flusso, come TextElement, FlowDocument, TextBlocke TextBox. Questa proprietà viene usata per controllare le caratteristiche e le variazioni tipografiche del testo (ad esempio maiuscole o grandi, creazione di apice e pedice e così via).

Nell'esempio seguente viene illustrato come impostare l'attributo Typography usando Paragraph come elemento di esempio.

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

La figura seguente mostra come viene eseguito il rendering di questo esempio.

Screenshot che mostra il testo con tipografia alterata.

La figura seguente mostra invece il rendering di un esempio simile con le proprietà tipografiche predefinite.

Screenshot che mostra il testo con tipografia predefinita.

Nell'esempio seguente viene illustrato come impostare la proprietà Typography a livello di codice.

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

Per altre informazioni sulla tipografia, vedere Tipografia in WPF.

Vedere anche