Compartir a través de


Información general del documento de Flow

Los documentos de flujo están diseñados para optimizar la visualización y la legibilidad. En lugar de establecerse en un diseño predefinido, los documentos se ajustan dinámicamente y reorganizan su contenido en función de variables de tiempo de ejecución, como el tamaño de la ventana, la resolución de dispositivos y las preferencias de usuario opcionales. Además, los documentos de flujo ofrecen características avanzadas de documentos, como la paginación y las columnas. En este tema se proporciona información general sobre los documentos de flujo y cómo crearlos.

¿Qué es un documento de flujo?

Un documento de flujo está diseñado para ajustar el contenido en función del tamaño de la ventana, la resolución del dispositivo y otras variables de entorno. Además, los documentos de flujo tienen una serie de características integradas, como la búsqueda, los modos de visualización que optimizan la legibilidad y la capacidad de cambiar el tamaño y la apariencia de las fuentes. Los documentos de flujo se usan mejor cuando la facilidad de lectura es el escenario principal de consumo de documentos. En cambio, los documentos fijos están diseñados para tener una presentación estática. Los documentos fijos son útiles cuando la fidelidad del contenido de origen es esencial. Vea Documentos en WPF para obtener más información sobre los distintos tipos de documentos.

En la ilustración siguiente se muestra un documento de flujo de ejemplo que se ve en varias ventanas de tamaños diferentes. A medida que cambia la zona de visualización, el contenido se ajusta para optimizar el uso del espacio disponible.

Reflujo de Contenido de Documento eDocs_FlowDocument

Como se muestra en la imagen anterior, el contenido de flujo puede incluir muchos componentes, como párrafos, listas, imágenes, etc. Estos componentes corresponden a elementos de marcado y objetos en el código de procedimiento. Veremos estas clases en detalle más adelante en la sección Clases relacionadas con el flujo de esta información general. Por ahora, este es un ejemplo de código sencillo que crea un documento de flujo que consta de un párrafo con texto en negrita y una lista.

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

En la ilustración siguiente se muestra el aspecto de este fragmento de código.

Captura de pantalla: ejemplo de FlowDocument representado

En este ejemplo, el FlowDocumentReader control se usa para hospedar el contenido del flujo. Consulte Flow Document Types (Tipos de documentos de flujo ) para obtener más información sobre los controles de hospedaje de contenido de flujo. ParagraphLos elementos , List, ListItemy Bold se usan para controlar el formato de contenido, en función de su orden en el marcado. Por ejemplo, el Bold elemento abarca solo parte del texto del párrafo; como resultado, solo esa parte del texto está en negrita. Si ha usado HTML, esto le resultará familiar.

Como se ha resaltado en la ilustración anterior, hay varias características integradas en documentos de flujo:

  • Búsqueda: permite al usuario realizar una búsqueda de texto completo de todo un documento.

  • Modo de visualización: el usuario puede seleccionar su modo de visualización preferido, incluido un modo de visualización de página única (página a tiempo), un modo de visualización de dos páginas a tiempo (formato de lectura de libros) y un modo de visualización de desplazamiento continuo (sin fondo). Para obtener más información sobre estos modos de visualización, vea FlowDocumentReaderViewingMode.

  • Controles de navegación de página: si el modo de visualización del documento usa páginas, los controles de navegación de página incluyen un botón para saltar a la página siguiente (la flecha abajo) o la página anterior (la flecha arriba), así como indicadores para el número de página actual y el número total de páginas. El volteo por páginas también se puede realizar mediante las teclas de dirección del teclado.

  • Zoom: los controles de zoom permiten al usuario aumentar o disminuir el nivel de zoom haciendo clic en los botones más o menos, respectivamente. Los controles de zoom también incluyen un control deslizante para ajustar el nivel de zoom. Para obtener más información, consulte Zoom.

Estas características se pueden modificar en función del control utilizado para hospedar el contenido del flujo. En la sección siguiente se describen los distintos controles.

Tipos de documentos de proceso

Mostrar el contenido del documento de flujo y cómo aparece depende del objeto que se usa para hospedar el contenido del flujo. Hay cuatro controles que admiten la visualización del contenido de flujo: FlowDocumentReader, FlowDocumentPageViewer, RichTextBoxy FlowDocumentScrollViewer. Estos controles se describen brevemente a continuación.

Nota:

FlowDocument es necesario para hospedar directamente el contenido del flujo, por lo que todos estos controles de visualización consumen un FlowDocument para habilitar el hospedaje de contenido de flujo.

FlowDocumentReader

FlowDocumentReader incluye características que permiten al usuario elegir dinámicamente entre varios modos de visualización, incluido un modo de visualización de página única (página a tiempo), un modo de visualización de dos páginas a tiempo (formato de lectura de libros) y un modo de visualización de desplazamiento continuo (sin fondo). Para obtener más información sobre estos modos de visualización, vea FlowDocumentReaderViewingMode. Si no necesita la capacidad de cambiar dinámicamente entre diferentes modos, FlowDocumentPageViewer y FlowDocumentScrollViewer proporcionan visores de flujo más ligeros, que se fijan en un modo de visualización determinado.

FlowDocumentPageViewer y FlowDocumentScrollViewer

FlowDocumentPageViewer muestra contenido en modo de presentación de una página a la vez, mientras que FlowDocumentScrollViewer muestra contenido en modo de desplazamiento continuo. Tanto FlowDocumentPageViewer como FlowDocumentScrollViewer están fijados a un modo de visualización particular. Compare con FlowDocumentReader, que incluye características que permiten al usuario elegir dinámicamente entre varios modos de visualización (según lo proporcionado por la enumeración FlowDocumentReaderViewingMode), a costa de ser más intensivo en recursos que FlowDocumentPageViewer o FlowDocumentScrollViewer.

De forma predeterminada, siempre se muestra una barra de desplazamiento vertical y una barra de desplazamiento horizontal se vuelve visible si es necesario. La interfaz de usuario predeterminada para FlowDocumentScrollViewer no incluye una barra de herramientas; sin embargo, la IsToolBarVisible propiedad se puede usar para habilitar una barra de herramientas integrada.

RichTextBox

Se usa un RichTextBox cuando se quiere permitir al usuario editar el contenido fluido. Por ejemplo, si desea crear un editor que permita a un usuario manipular elementos como tablas, formato cursiva y negrita, etc., usaría un RichTextBox. Consulte Información general sobre RichTextBox para obtener más información.

Nota:

El contenido de flujo dentro de un RichTextBox no se comporta exactamente igual que el contenido de flujo contenido en otros controles. Por ejemplo, no hay columnas en RichTextBox y, por lo tanto, no hay ningún comportamiento de cambio de tamaño automático. Además, las características integradas normalmente de contenido de flujo, como la búsqueda, el modo de visualización, la navegación por páginas y el zoom, no están disponibles en .RichTextBox

Creación de contenido de flujo

El contenido de flujo puede ser complejo, que consta de varios elementos, como texto, imágenes, tablas e incluso UIElement clases derivadas como controles. Para comprender cómo crear contenido de flujo complejo, los siguientes puntos son críticos:

  • Clases relacionadas con el flujo: cada clase usada en el contenido de flujo tiene un propósito específico. Además, la relación jerárquica entre las clases de flujo le ayuda a comprender cómo se usan. Por ejemplo, las clases derivadas de la Block clase se usan para contener otros objetos mientras que las clases derivadas de Inline contienen objetos que se muestran.

  • Esquema de contenido: un documento de flujo puede requerir un número considerable de elementos anidados. El esquema de contenido especifica posibles relaciones primarias o secundarias entre elementos.

En las secciones siguientes se repasará cada una de estas áreas con más detalle.

En el diagrama siguiente se muestran los objetos que se suelen usar con el contenido de flujo:

Diagrama: jerarquía de clases de elemento de contenido de flujo

Para los fines del contenido de flujo, hay dos categorías importantes:

  1. Clases derivadas de bloques: también denominadas "Elementos de contenido de bloque" o simplemente "Elementos de Bloque". Los elementos que heredan de Block se pueden usar para agrupar elementos en un elemento primario común o para aplicar atributos comunes a un grupo.

  2. Clases derivadas en línea: también denominadas "Elementos de contenido insertados" o simplemente "Elementos insertados". Los elementos que heredan de Inline se encuentran dentro de un elemento de bloque u otro elemento en línea. Los elementos en línea se suelen usar como el contenedor directo del contenido que se muestra en la pantalla. Por ejemplo, un Paragraph (elemento Block) puede contener un Run elemento (Elemento insertado), pero contiene Run realmente el texto que se representa en la pantalla.

Cada clase de estas dos categorías se describe brevemente a continuación.

Clases derivadas de bloques

párrafo

Paragraph normalmente se usa para agrupar el contenido en un párrafo. El uso más sencillo y común de Paragraph es crear un párrafo de texto.

<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

Sin embargo, también puede contener otros elementos derivados en línea, como verá a continuación.

Sección

Section se utiliza únicamente para contener otros elementos derivados de Block. No aplica ningún formato predeterminado a los elementos que contiene. Sin embargo, los valores de propiedad establecidos en se Section aplican a sus elementos secundarios. Una sección también permite recorrer en iteración mediante programación su colección secundaria. Section se usa de forma similar a la <etiqueta DIV> en HTML.

En el ejemplo siguiente, se definen tres párrafos en un Section. La sección tiene un Background valor de propiedad rojo, por lo que el color de fondo de los párrafos también es rojo.

<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 permite que los elementos UIElement (es decir, un Button) se inserten en contenido de flujo derivado de bloques. InlineUIContainer (ver abajo) se usa para integrar elementos UIElement en contenido de flujo derivado en línea. BlockUIContainer y InlineUIContainer son importantes porque no hay ninguna otra manera de usar un UIElement elemento en el contenido de flujo a menos que esté contenido dentro de uno de estos dos elementos.

En el ejemplo siguiente se muestra cómo usar el BlockUIContainer elemento para hospedar UIElement objetos dentro del contenido del flujo.

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

En la ilustración siguiente se muestra cómo se representa este ejemplo:

Captura de pantalla que muestra un UIElement incrustado en el contenido del flujo.

Lista

List se usa para crear una lista con viñetas o numéricas. Establezca la propiedad MarkerStyle a un valor de enumeración TextMarkerStyle para definir el estilo de la lista. En el ejemplo siguiente se muestra cómo crear una lista sencilla.

<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 es el único elemento de flujo que usa ListItemCollection para administrar elementos secundarios.

Tabla

Table se usa para crear una tabla. Table es similar al Grid elemento, pero tiene más funcionalidades y, por lo tanto, requiere una mayor sobrecarga de recursos. Dado que Grid es un UIElement, no se puede usar en contenido de flujo a menos que esté contenido en un BlockUIContainer o un InlineUIContainer. Para obtener más información sobre Table, vea Descripción general de la tabla.

Clases derivadas integradas

Ejecutar

Run se usa para contener texto sin formato. Podrías esperar que los Run objetos se usen ampliamente en el contenido de flujo. Sin embargo, en el marcado, no es necesario utilizar elementos Run de manera explícita. Run debe usarse al crear o manipular documentos de flujo a través de código. Por ejemplo, en el marcado siguiente, el primero Paragraph especifica explícitamente el Run elemento mientras que el segundo no. Ambos párrafos generan una salida idéntica.

<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 partir de .NET Framework 4, la Text propiedad del Run objeto es una propiedad de dependencia. Puede enlazar la Text propiedad a un origen de datos, como .TextBlock La Text propiedad es totalmente compatible con el enlace unidireccional. La Text propiedad también admite el enlace bidireccional, excepto para RichTextBox. Para obtener un ejemplo, consulte Run.Text.

Intervalo

Span agrupa otros elementos de contenido en línea juntos. No se aplica ninguna representación inherente al contenido dentro de un Span elemento. Sin embargo, los elementos que heredan de Span incluir Hyperlink, BoldItalicy Underline aplican formato al texto.

A continuación se muestra un ejemplo de que Span se usa para contener contenido insertado, incluido texto, un Bold elemento y 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>

En la captura de pantalla siguiente se muestra cómo se representa este ejemplo.

Captura de pantalla: ejemplo de intervalo representado

InlineUIContainer

InlineUIContainer permite que un elemento UIElement (es decir, un control como Button) se inserte en un elemento de contenido Inline. Este elemento es el equivalente en línea de BlockUIContainer descrito anteriormente. A continuación se muestra un ejemplo que usa InlineUIContainer para insertar un Button en línea en 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 no necesita usarse explícitamente en la marcación. Si lo omite, se creará un InlineUIContainer de todas formas cuando se compile el código.

Figura y flotador

Figure y Floater se usan para insertar contenido en documentos de flujo con propiedades de selección de ubicación que se pueden personalizar independientemente del flujo de contenido principal. Figure Los elementos o Floater a menudo se usan para resaltar o acentuar partes del contenido, para hospedar imágenes auxiliares u otro contenido dentro del flujo de contenido principal, o para insertar contenido relacionado de forma flexible, como anuncios.

En el ejemplo siguiente se muestra cómo insertar un elemento Figure en un párrafo de texto.

<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

En la ilustración siguiente se muestra cómo se representa este ejemplo.

Captura de pantalla: Ilustración de ejemplo

Figure y Floater difieren de varias maneras y se usan para diferentes escenarios.

Figura:

  • Puede colocarse: puede establecer sus anclajes horizontales y verticales para anclarlos en relación con la página, el contenido, la columna o el párrafo. También puede usar sus HorizontalOffset propiedades y VerticalOffset para especificar desplazamientos arbitrarios.

  • Se puede ajustar el tamaño a más de una columna: puede establecer la altura y el ancho de Figure a múltiplos de la altura o el ancho de la página, el contenido o la columna. Tenga en cuenta que, en el caso de página y contenido, no se permiten múltiplos mayores que 1. Por ejemplo, puede establecer el ancho de un Figure para que sea "0,5 página" o "0,25 contenido" o "2 columna". También puede establecer el alto y el ancho en valores absolutos de píxeles.

  • No paginará: si el contenido dentro de Figure no cabe dentro de Figure, mostrará el contenido que quepa y el contenido restante se perderá.

Flotador:

  • No se puede colocar en una posición específica y se mostrará donde haya espacio disponible. No se puede establecer el desplazamiento o anclar un Floater.

  • No se puede ajustar el tamaño a más de una columna: por defecto, Floater se ajusta a una columna. Tiene una Width propiedad que se puede establecer en un valor absoluto en píxeles, pero si este valor es mayor que el ancho de una columna, se ignora y el flotador se dimensiona para una sola columna. Puede ajustar el tamaño a menos de una columna estableciendo el ancho de píxel correcto, pero el ajuste de tamaño no es relativo a columnas, por lo que "0,5Column" no es una expresión válida para Floater el ancho. Floater no tiene ninguna propiedad de altura y su altura no se puede establecer; su altura depende del contenido.

  • Floater paginados: Si su contenido en su ancho especificado se extiende a más de una altura de columna, el contenido flotante se corta y se paginan a la columna siguiente, a la página siguiente, etc.

Figure es un buen lugar para colocar contenido independiente en el que desea controlar el tamaño y el posicionamiento, y está seguro de que el contenido cabe en el tamaño especificado. Floater es un buen lugar para poner más contenido de flujo libre que fluye de forma similar al contenido de la página principal, pero está separado de él.

LineBreak

LineBreak provoca un salto de línea en el flujo de contenido. En el ejemplo siguiente se muestra el uso de 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>

En la captura de pantalla siguiente se muestra cómo se representa este ejemplo.

Captura de pantalla: ejemplo de LineBreak

Elementos de colección de flujo

En muchos de los ejemplos anteriores, los BlockCollection y InlineCollection se usan para construir contenido de flujo mediante programación. Por ejemplo, para agregar elementos a un Paragraph, puede usar la sintaxis:

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

Esto añade un Run al InlineCollection del Paragraph. Esto es lo mismo que el implícito Run que se encuentra dentro de un Paragraph elemento en el marcado:

<Paragraph>
Some Text
</Paragraph>

Como ejemplo de uso del BlockCollection, en el ejemplo siguiente se crea un nuevo Section y, a continuación, se usa el método Add para agregar un nuevo Paragraph a los Section contenidos.

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...")))

Además de agregar elementos a una colección de flujo, también puede quitar elementos. En el ejemplo siguiente se elimina el último Inline elemento de Span.

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

En el ejemplo siguiente se borra todo el contenido (Inline elementos) de Span.

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

Al trabajar con contenido de flujo mediante programación, es probable que use extensamente estas colecciones.

Si un elemento de flujo usa un InlineCollection (En línea) o un BlockCollection (Bloques) para contener sus elementos secundarios depende del tipo de elementos secundarios (Block o Inline) que pueda contener el elemento primario. Las reglas de contención de los elementos de contenido de flujo se resumen en el esquema de contenido de la sección siguiente.

Nota:

Hay un tercer tipo de colección que se usa con el contenido de flujo, ListItemCollection, pero esta colección solo se usa con .List Además, hay varias colecciones usadas con Table. Consulte Información general sobre la tabla para obtener más información.

Esquema de contenido

Dado el número de diferentes elementos de contenido de flujo, puede ser abrumador realizar un seguimiento del tipo de elementos secundarios que puede contener un elemento. En el diagrama siguiente se resumen las reglas de contención de los elementos de flujo. Las flechas representan las posibles relaciones de padre o hijo.

Diagrama: esquema de contención de contenido de flujo

Como se puede ver en el diagrama anterior, los elementos secundarios permitidos para un elemento no están determinados necesariamente por si es un Block elemento o un Inline elemento. Por ejemplo, un Span elemento (un Inline elemento) solo puede tener Inline elementos secundarios mientras que un Figure elemento (también un Inline elemento) solo puede tener Block elementos secundarios. Por lo tanto, un diagrama es útil para determinar rápidamente qué elemento se puede contener en otro. Por ejemplo, vamos a usar el diagrama para determinar cómo construir el contenido de flujo de .RichTextBox

1. Un RichTextBox debe contener un FlowDocument que, a su vez, debe contener un objeto derivado de Block. A continuación se muestra el segmento correspondiente del diagrama anterior.

Diagrama: Reglas de contención de RichTextBox

Hasta ahora, esto es lo que podría parecer el marcado.

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

2. Según el diagrama, hay varios Block elementos entre los que elegir, incluyendo Paragraph, Section, Table, Listy BlockUIContainer (vea Block-derived classes above). Supongamos que queremos un Table. Según el diagrama anterior, un Table contiene un TableRowGroup que contiene elementos TableRow, los cuales contienen elementos TableCell que contienen un objeto derivado de Block. A continuación se muestra el segmento correspondiente a Table, tomado del diagrama anterior.

Diagrama: Esquema padre/hijo para tabla

A continuación se muestra el marcado correspondiente.

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

3. De nuevo, se requiere uno o más Block elementos debajo de un TableCell. Para simplificarlo, vamos a colocar texto dentro de la celda. Podemos hacerlo mediante un elemento Paragraph con un Run. A continuación se muestran los segmentos correspondientes del diagrama que muestran que un Paragraph elemento puede tomar un Inline elemento y que un Run elemento (un Inline elemento) solo puede tomar texto sin formato.

Diagrama: Esquema primario/secundario para paragraph

Diagrama: Esquema padre/hijo para ejecución

A continuación se muestra el ejemplo completo en el lenguaje de marcado.

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

Personalización de texto

Normalmente, el texto es el tipo de contenido más frecuente en un documento de flujo. Aunque los objetos introducidos anteriormente se pueden usar para controlar la mayoría de los aspectos de cómo se representa el texto, hay otros métodos para personalizar el texto que se trata en esta sección.

Decoraciones de texto

Las decoraciones de texto permiten aplicar los efectos de subrayado, sobrerrañado, línea base y tachado al texto (consulte las imágenes a continuación). Estas decoraciones se agregan mediante la TextDecorations propiedad expuesta por varios objetos, como Inline, Paragraph, TextBlocky TextBox.

En el ejemplo siguiente se muestra cómo establecer la TextDecorations propiedad de 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

En la ilustración siguiente se muestra cómo se representa este ejemplo.

Captura de pantalla: Texto con efecto de tachado predeterminado

Las ilustraciones siguientes muestran cómo se representan las decoraciones Overline, Baseline y Underline , respectivamente.

Captura de pantalla: TextDecorator de superposición

Captura de pantalla: Efecto de línea base predeterminado en el texto

Captura de pantalla: Texto con efecto de subrayado predeterminado

Tipografía

La propiedad Typography es expuesta por la mayoría del contenido relacionado con el flujo, incluyendo TextElement, FlowDocument, TextBlock y TextBox. Esta propiedad se usa para controlar características tipográficas o variaciones de texto (es decir, mayúsculas pequeñas o grandes, haciendo superíndices y subíndices, etc.).

En el ejemplo siguiente se muestra cómo establecer el Typography atributo utilizando Paragraph como elemento de ejemplo.

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

En la ilustración siguiente se muestra cómo se representa este ejemplo.

Captura de pantalla que muestra el texto con tipografía modificada.

En cambio, en la ilustración siguiente se muestra cómo se representa un ejemplo similar con las propiedades tipográficas predeterminadas.

Captura de pantalla que muestra el texto con la tipografía predeterminada.

En el ejemplo siguiente se muestra cómo establecer la Typography propiedad mediante programación.

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

Consulte Tipografía en WPF para obtener más información sobre la tipografía.

Consulte también