Cenni preliminari sui documenti dinamici
I documenti dinamici sono progettati per ottimizzare la visualizzazione e la leggibilità. Anziché essere impostati su un layout predefinito, questi documenti consentono di adattare e ridisporre il contenuto in modo dinamico in base alle variabili in fase di esecuzione, ad esempio, le dimensioni della finestra, la risoluzione del dispositivo e le preferenze facoltative dell'utente. Questi documenti offrono anche funzionalità avanzate del documento, quali paginazione e colonne. Questo argomento offre una panoramica dei documenti dinamici e di come crearli.
Che cos'è un documento dinamico
I documenti dinamici sono progettati per "adattare il flusso del contenuto" in base alle dimensioni della finestra, alla risoluzione del dispositivo e ad altre variabili di ambiente. Inoltre, i documenti dinamici dispongono di numerose funzionalità incorporate tra cui ricerca, modalità di visualizzazione che ottimizzano la leggibilità e possibilità di modificare le dimensioni e l'aspetto dei tipi di carattere. I documenti dinamici sono particolarmente adatti quando la facilità di lettura è il principale requisito d'uso per il documento. I documenti statici, al contrario, sono progettati per avere una presentazione statica e risultano utili quando la fedeltà del contenuto di origine è fondamentale. Per altre informazioni sui diversi tipi di documenti, vedere Documenti in WPF.
La figura seguente mostra un documento dinamico di esempio visualizzato in molte finestre di dimensioni diverse. Quando l'area di visualizzazione cambia, il contenuto viene ridisposto per un uso ottimale dello spazio disponibile.
Come illustrato nell'immagine precedente, il contenuto dinamico può includere molti componenti, tra cui paragrafi, elenchi, immagini e altro. Questi componenti corrispondono agli elementi nel markup e agli oggetti nel codice procedurale. Queste classi verranno esaminate dettagliatamente più avanti nella sezione Classi correlate al flusso di questi cenni preliminari. Di seguito è riportato un semplice esempio di codice che crea un documento dinamico costituito da un paragrafo con testo in grassetto e da 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
Nella figura riportata di seguito viene illustrato il frammento di codice in questione.
In questo esempio il FlowDocumentReader controllo viene usato per ospitare il contenuto del flusso. Per altre informazioni sui controlli che ospitano il contenuto del flusso vedere Tipi di documenti dinamici. ParagraphGli elementi , List, ListIteme 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 si ha esperienza con il linguaggio HTML, questo meccanismo sarà familiare.
Come evidenziato nella figura precedente, esistono numerose funzionalità incorporate nei documenti dinamici:
Ricerca: consente all'utente di eseguire ricerche full-text di un intero documento.
Modalità di visualizzazione: consente all'utente di selezionare la modalità di visualizzazione preferita, inclusa una modalità di visualizzazione a pagina singola (una pagina per volta), una modalità di visualizzazione a pagina doppia (formato lettura libro) e una modalità di visualizzazione a spostamento continuo (infinito). Per altre informazioni su queste modalità di visualizzazione, vedere FlowDocumentReaderViewingMode.
Controlli di spostamento tra le pagine: se la modalità di visualizzazione del documento usa le pagine, i controlli di spostamento tra le pagine includono un pulsante per passare alla pagina successiva (freccia verso il basso) o alla pagina precedente ( freccia verso l'alto), oltre a indicatori del numero della pagina corrente e del numero totale di pagine. È anche possibile scorrere le pagine usando i tasti di direzione della tastiera.
Zoom: i controlli dello zoom consentono all'utente di aumentare o ridurre il livello dello zoom facendo clic sui pulsanti più o meno, rispettivamente. I controlli dello zoom includono anche un dispositivo di scorrimento per regolare il livello dello zoom. Per ulteriori informazioni, vedere Zoom.
Queste funzionalità possono essere modificate in base al controllo usato per ospitare il contenuto del flusso. I vari controlli vengono descritti nella sezione seguente.
Tipi di documenti dinamici
La visualizzazione del contenuto del documento dinamico e la modalità di visualizzazione corrispondente dipendono dall'oggetto usato per ospitare il contenuto del flusso. Sono disponibili quattro controlli che supportano la visualizzazione del contenuto del flusso: FlowDocumentReader, FlowDocumentPageViewerRichTextBox, e FlowDocumentScrollViewer. Questi controlli vengono descritti brevemente di seguito.
Nota
FlowDocument è necessario per ospitare direttamente il contenuto del flusso, quindi tutti questi controlli di visualizzazione utilizzano per FlowDocument abilitare l'hosting del contenuto del flusso.
FlowDocumentReader
FlowDocumentReader include funzionalità che consentono all'utente di scegliere dinamicamente tra varie 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 scorrimento continuo (senza fondo). Per altre informazioni su queste modalità di visualizzazione, vedere FlowDocumentReaderViewingMode. Se non è necessaria la possibilità di passare dinamicamente da una modalità FlowDocumentPageViewer di visualizzazione all'altra e FlowDocumentScrollViewer fornire visualizzatori di contenuto di flusso più leggeri 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. Confrontare con FlowDocumentReader, che include funzionalità che consentono all'utente di scegliere in modo dinamico tra varie modalità di visualizzazione (come fornito dall'enumerazione FlowDocumentReaderViewingMode ), a costo di un utilizzo elevato di risorse rispetto FlowDocumentPageViewer a o FlowDocumentScrollViewer.
Per impostazione predefinita, viene sempre visualizzata una barra di scorrimento verticale e in caso di necessità diventa visibile una barra di scorrimento orizzontale. L'interfaccia utente predefinita per FlowDocumentScrollViewer non include una barra degli strumenti, ma la IsToolBarVisible proprietà può essere usata per abilitare una barra degli strumenti predefinita.
RichTextBox
Si usa un oggetto 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 oggetto RichTextBox. Per altre informazioni, vedere Cenni preliminari sul controllo RichTextBox.
Nota
Il contenuto del flusso all'interno di un RichTextBox oggetto non si comporta esattamente come il contenuto di flusso contenuto in altri controlli. Ad esempio, non ci sono colonne in un RichTextBox e quindi nessun comportamento di ridimensionamento automatico. Inoltre, le funzionalità incorporate in genere di contenuto di flusso, ad esempio la modalità di ricerca, la modalità di visualizzazione, lo spostamento delle pagine e lo zoom non sono disponibili all'interno di un oggetto RichTextBox.
Creazione di contenuto dinamico
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 la modalità di creazione di contenuto dinamico complesso, i punti riportati di seguito 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 facilita la comprensione della modalità d'uso. Ad esempio, le classi derivate dalla Block classe vengono utilizzate per contenere altri oggetti mentre le classi derivate da Inline contengono oggetti visualizzati.
Schema del contenuto: un documento dinamico può richiedere un numero considerevole di elementi annidati. Nello schema del contenuto vengono specificate le possibili relazioni padre/figlio tra elementi.
Ognuna di queste aree verrà esaminata in maniera dettagliata nella sezioni seguenti.
Classi correlate al flusso
Il diagramma seguente illustra gli oggetti usati più di frequente con il contenuto dinamico:
Ai fini del contenuto dinamico, esistono due categorie importanti:
Classi derivate da Block: definite anche "elementi del contenuto di Block" o semplicemente "elementi Block". 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.
Classi derivate da Inline: definite anche "elementi del contenuto di 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 contenitori diretti del contenuto di cui viene eseguito il rendering sullo schermo. Ad esempio, un Paragraph (elemento Block) può contenere un Run elemento (elemento Inline), ma contiene Run effettivamente il testo di cui viene eseguito il rendering sullo schermo.
Ogni classe di queste due categorie è descritta brevemente di seguito.
Classi derivate da Block
Paragraph
Paragraph viene in genere utilizzato per raggruppare il contenuto in un paragrafo. L'uso più semplice e più comune di Paragraph è 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 utilizzato solo per contenere altri Blockelementi derivati da . Non applica alcuna formattazione predefinita agli elementi in essa contenuti. Tuttavia, tutti i valori delle proprietà impostati in un Section oggetto si applicano ai relativi elementi figlio. Una sezione consente inoltre di effettuare iterazioni a livello di codice mediante la relativa raccolta figlio. Section viene usato in modo simile al <tag DIV> in HTML.
Nell'esempio seguente, tre paragrafi sono definiti in un oggetto Section. La sezione ha un Background valore della proprietà 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 agli UIElement elementi (ad esempio a Button) di essere incorporati nel contenuto del flusso derivato da blocchi. InlineUIContainer (vedere di seguito) viene usato per incorporare UIElement elementi nel contenuto del flusso derivato da inline. BlockUIContainer e InlineUIContainer sono importanti perché non esiste un altro modo per usare un UIElement oggetto nel contenuto del flusso, a meno che non sia contenuto all'interno di uno di questi due elementi.
Nell'esempio seguente viene illustrato come usare l'elemento BlockUIContainer per ospitare UIElement oggetti all'interno del contenuto del flusso.
<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:
Elenco
List viene utilizzato per creare un elenco puntato o numerico. Impostare la MarkerStyle proprietà su un TextMarkerStyle valore di enumerazione per determinare lo stile dell'elenco. L'esempio seguente mostra 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 per ListItemCollection gestire gli elementi figlio.
Tabella
Table viene utilizzato per creare una tabella. Table è simile all'elemento Grid , ma ha più funzionalità e pertanto richiede un sovraccarico maggiore delle risorse. Poiché Grid è un UIElementoggetto , non può essere usato nel contenuto del flusso a meno che non sia contenuto in un BlockUIContainer oggetto o InlineUIContainer. Per altre informazioni su , vedere Cenni preliminari sulla Tabletabella.
Classi derivate da Inline
Esegui
Run viene utilizzato per contenere testo non formattato. È possibile che Run gli oggetti vengano usati ampiamente nel contenuto di flusso. Tuttavia, nel markup, Run gli elementi non devono essere usati in modo esplicito. Run è necessario per 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 output identici.
<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 Text proprietà dell'oggetto Run è una proprietà di dipendenza. È possibile associare la proprietà a un'origine Text dati, ad esempio .TextBlock La Text proprietà supporta completamente l'associazione unidirezionale. La Text proprietà supporta anche l'associazione bidirezionale, ad eccezione di RichTextBox. Per un esempio, vedere Run.Text.
Span
Span raggruppa altri elementi di contenuto inline. Nessun rendering intrinseco viene applicato al contenuto all'interno di un Span elemento. Tuttavia, gli elementi che ereditano da Span , BoldHyperlinkItalic e Underline applicano la formattazione al testo.
Di seguito è riportato un esempio di oggetto Span usato per contenere contenuto inline, tra cui testo, un Bold elemento e un oggetto 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 illustra il rendering di questo esempio.
InlineUIContainer
InlineUIContainer consente UIElement agli elementi (ad esempio un controllo come Button) di essere incorporati in un Inline elemento di contenuto. Questo elemento è l'equivalente inline descritto BlockUIContainer in precedenza. Di seguito è riportato un esempio che usa InlineUIContainer per inserire un Button oggetto inline in un oggetto 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 usato in modo esplicito nel markup. Se lo si omette, verrà comunque creato un oggetto InlineUIContainer quando il codice viene compilato.
Figure e Floater
Figure e Floater vengono usati per incorporare il contenuto nei documenti di Flow con proprietà di posizionamento che possono essere personalizzate indipendentemente dal flusso di contenuto primario. Figure o Floater gli 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.
Nell'esempio seguente viene illustrato come incorporare un oggetto 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 illustra come viene eseguito il rendering dell'esempio.
Figure e Floater differiscono in diversi modi e vengono usati per diversi scenari.
Figure:
Può essere posizionata: è possibile impostarne gli ancoraggi orizzontali e verticali per ancorarla in relazione alla pagina, al contenuto, alla colonna o al paragrafo. È anche possibile utilizzare HorizontalOffset le relative proprietà e VerticalOffset per specificare offset arbitrari.
Può essere ridimensionata in più colonne: è possibile impostare Figure l'altezza e la larghezza su più colonne, altezza o larghezza della pagina, del contenuto o della colonna. Nel caso della pagina e del contenuto, i multipli superiori a 1 non sono consentiti. Ad esempio, è possibile impostare la larghezza di un oggetto Figure su "0.5 page" o "0.25 content" o "2 Column". È anche possibile impostare l'altezza e la larghezza su valori di pixel assoluti.
Non impagina: se il contenuto all'interno di un Figure oggetto non rientra in Figure, eseguirà il rendering di qualsiasi contenuto adatto e il contenuto rimanente andrà perso
Floater:
Non può essere posizionato ed esegue il rendering ovunque vi sia uno spazio a disposizione. Non è possibile impostare l'offset o l'ancoraggio di un oggetto Floater.
Non è possibile ridimensionare più di una colonna: per impostazione predefinita, Floater le dimensioni vengono ridimensionate in una colonna. Ha una Width proprietà che può essere impostata su un valore di pixel assoluto, ma se questo valore è maggiore di una larghezza di colonna viene ignorato e il floater viene ridimensionato in 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 la larghezza. Floater non ha proprietà height e non può essere impostata l'altezza, l'altezza dipende dal contenuto
Floater paginates: se il contenuto alla larghezza specificata si estende a più di 1 altezza di colonna, floater interrompe e impagina nella colonna successiva, la 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 punto in cui inserire contenuto più libero che scorre in modo simile al contenuto della pagina principale, ma è separato da esso.
LineBreak
LineBreak causa un'interruzione di riga nel contenuto del flusso. L'esempio seguente illustra 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 illustra il rendering di questo esempio.
Elementi della raccolta di flusso
In molti degli esempi precedenti, BlockCollection e InlineCollection vengono usati per costruire il contenuto del flusso a livello di codice. Ad esempio, per aggiungere elementi a un Paragraphoggetto , è possibile usare la sintassi :
myParagraph.Inlines.Add(new Run("Some text"));
In questo modo viene aggiunto un Run oggetto all'oggetto InlineCollection dell'oggetto Paragraph. Si tratta dello stesso elemento implicito Run trovato all'interno di un Paragraph oggetto nel markup:
<Paragraph>
Some Text
</Paragraph>
Come esempio di utilizzo BlockCollectiondi , l'esempio seguente crea un nuovo Section oggetto e quindi usa il metodo Add per aggiungere un nuovo Paragraph al Section contenuto.
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 flusso, è anche possibile rimuovere elementi. Nell'esempio seguente viene eliminato l'ultimo Inline elemento dell'oggetto Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
spanx.Inlines.Remove(spanx.Inlines.LastInline)
Nell'esempio seguente vengono cancellati tutti i contenuti (Inline elementi) da Span.
spanx.Inlines.Clear();
spanx.Inlines.Clear()
Quando si usa il contenuto dinamico a livello di codice, è probabile che queste raccolte vengano usate diffusamente.
L'uso di un InlineCollection elemento di flusso (Inlines) o BlockCollection (Blocks) per contenere i relativi elementi figlio dipende dal tipo di elementi figlio (Block o Inline) che può essere contenuto dall'elemento padre. Le regole di contenimento per gli elementi di contenuto dinamico sono riepilogate nello schema del contenuto nella sezione seguente.
Nota
Esiste un terzo tipo di raccolta usato con il contenuto del flusso, ma ListItemCollectionquesta raccolta viene usata solo con un oggetto List. Sono inoltre disponibili diverse raccolte usate con Table. Per altre informazioni, vedere Cenni preliminari sull'elemento Table.
Schema del contenuto
Dato il gran numero di elementi diversi del contenuto dinamico, può essere complicato tenere traccia del tipo di elementi figlio che può essere contenuto da un elemento. Il diagramma seguente riepiloga le regole di contenimento per gli elementi di flusso. Le frecce rappresentano le possibili relazioni padre/figlio.
Come si può vedere dal diagramma precedente, gli elementi figlio consentiti per un elemento non sono necessariamente determinati dal fatto che si tratti di un Block elemento o di un Inline elemento. Ad esempio, un Span oggetto (un Inline elemento) può avere Inline solo elementi figlio, mentre un Figure elemento (anche un Inline elemento) può avere Block solo elementi figlio. Pertanto, un diagramma è utile per determinare rapidamente quale elemento può essere contenuto in un altro elemento. Ad esempio, si userà il diagramma per determinare come costruire il contenuto del flusso di un oggetto RichTextBox.
1. Un RichTextBox oggetto deve contenere un oggetto FlowDocument che a sua volta deve contenere un Blockoggetto derivato da . Di seguito viene riportato il segmento corrispondente del diagramma precedente.
Fino a questo punto, l'aspetto del markup potrebbe essere simile al seguente.
<RichTextBox>
<FlowDocument>
<!-- One or more Block-derived object… -->
</FlowDocument>
</RichTextBox>
2. In base al diagramma, sono disponibili diversi Block elementi tra cui Paragraph, , SectionTable, Liste BlockUIContainer (vedere Classi derivate da blocchi sopra). Si supponga di volere un oggetto Table. In base al diagramma precedente, un Table oggetto contiene elementi TableRowGroup contenenti TableRow elementi che contengono TableCell un Blockoggetto derivato da . Di seguito è riportato il segmento corrispondente per Table tratto dal diagramma precedente.
Ecco il markup corrispondente.
<RichTextBox>
<FlowDocument>
<Table>
<TableRowGroup>
<TableRow>
<TableCell>
<!-- One or more Block-derived object… -->
</TableCell>
</TableRow>
</TableRowGroup>
</Table>
</FlowDocument>
</RichTextBox>
3. Anche in questo caso, uno o più Block elementi sono necessari sotto un oggetto TableCell. Per rendere più chiaro l'esempio, viene inserito del testo nella cella. A tale scopo, è possibile usare un Paragraph oggetto con un Run elemento . Di seguito sono riportati i segmenti corrispondenti del diagramma che mostra che un Paragraph oggetto può accettare un Inline elemento e che un (Inlineelemento Run ) può accettare solo testo normale.
Di seguito viene mostrato l'intero esempio a livello di 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 dinamico. Sebbene gli oggetti illustrati in precedenza possano essere usati per controllare la maggior parte degli aspetti della modalità di rendering del testo, esistono alcuni altri metodi per la personalizzazione del testo descritti in questa sezione.
Decorazioni di testo
Le decorazioni di testo consentono di applicare gli effetti sottolineato, linea sopra, linea di base e barrato al testo, come illustrato nelle figure riportate di seguito. Queste decorazioni vengono aggiunte usando la TextDecorations proprietà esposta da diversi oggetti, tra cui Inline, ParagraphTextBlock, e TextBox.
Nell'esempio seguente viene illustrato come impostare la proprietà TextDecorations di un oggetto 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 illustra il rendering di questo esempio.
Le figure seguenti mostrano rispettivamente il rendering delle decorazioni Overline, Baseline e Underline.
Tipografia
La Typography proprietà viene esposta dalla maggior parte del contenuto correlato al flusso, tra cui TextElement, FlowDocumentTextBlock, e TextBox. Questa proprietà viene usata per controllare le caratteristiche o le variazioni tipografiche del testo (ad esempio maiuscoletto o maiuscolo, pedici e sottoscrizioni 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 illustra il rendering di questo esempio.
La figura seguente mostra invece il rendering dello stesso esempio con le proprietà tipografiche predefinite.
Nell'esempio seguente viene illustrato come impostare la Typography proprietà 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 sulle proprietà tipografiche, vedere Funzionalità tipografiche di WPF.
Vedi anche
.NET Desktop feedback