Usando y creando documentos en WPF (FlowDocument)


La creación e impresión de documentos en Windows Forms es muy cansón y complicado, en WPF es mucho más fácil.

¿Que son?

 Los Flow Documents son como lo dice el nombre, documentos que pueden ser creados y mostrados en una aplicación WPF. Consisten primordialmente en textos, con figuras y otros elementos incluidos en el entorno. Consisten de dos diferentes tipos de elementos: elementos en bloque, los cuales definen bloques de secciones de texto, siempre tienen un salto de línea entre cada elemento; y elementos en línea, que proveen formatos y efectos de texto en línea. Los Flow Documents deben ser creados dentro de un contenedor, además los contenedores nos proveen de Zoom, Paginación, columnas y cuando se cambia de tamaño, el texto se adecua al tamaño del elemento.

Creando Flow Documents

Para crear un Flow Document, podemos crearlo dentro del contenedor FlowDocumentScrollViewer, que soporta las barras de desplazamiento: Ejemplo:

<FlowDocumentScrollViewer>
            <FlowDocument>
                <Paragraph>
                    Un ejemplo de un Flow Document, dentro de un FlowDocumentScrollViewer
                    ....
                    Un ejemplo de un Flow Document, dentro de un FlowDocumentScrollViewer
                </Paragraph>
            </FlowDocument>
        </FlowDocumentScrollViewer>

 1.FlowDocumentScrollViewer

Todo el contenido dentro de los flow documents es acomodado (wrapped).

Formateando Flow Documents

 Todos los elementos en línea y en bloques tienen muchas propiedades que podemos usar para formatear el texto, como por ejemplo el fondo, el color, tipo, tamaño, estilo de la letra entre otras.

Los cambios hechos a dichas propiedades son aplicados a todo el texto que esta encerrado en el elemento, hay otras propiedades que solo aplican para los elementos en bloque y son: color, grosor del borte, espaciamiento del texto, márgenes, alineación del texto.

Por ejemplo a nuestro ejemplo anterior podemos modificar unas cuantas propiedades del elemento Paragraph:

<Paragraph Background="Moccasin" BorderBrush="Red" BorderThickness="2" FontSize="45" Foreground="Green" Margin="5">
                    Un ejemplo de un Flow Document, dentro de un FlowDocumentScrollViewer
                    ....
                    Un ejemplo de un Flow Document, dentro de un FlowDocumentScrollViewer
                </Paragraph>

 2.Formatos

Elementos en Bloque:

Como hemos visto, los elementos en bloque acomodan el texto dentro del documento, entre estos elementos tenemos:

Paragraph: Este es el más básico de los elementos en bloque y definen un bloque de texto dentro de un párrafo, en el siguiente ejemplo tendremos varios elementos Paragraph:

  <FlowDocumentScrollViewer>
            <FlowDocument>
                <Paragraph>
                    Me gustas cuando callas porque estás como ausente,
y me oyes desde lejos, y mi voz no te toca.
Parece que los ojos se te hubieran volado
y parece que un beso te cerrara la boca.
                </Paragraph>
                <Paragraph>
                    Como todas las cosas están llenas de mi alma
emerges de las cosas, llena del alma mía.
Mariposa de sueño, te pareces a mi alma,
y te pareces a la palabra melancolía.
                </Paragraph>
                <Paragraph>
                    Me gustas cuando callas y estás como distante.
Y estás como quejándote, mariposa en arrullo.
Y me oyes desde lejos, y mi voz no te alcanza:
déjame que me calle con el silencio tuyo.
                </Paragraph>
                <Paragraph>
                    Déjame que te hable también con tu silencio
claro como una lámpara, simple como un anillo.
Eres como la noche, callada y constelada.
Tu silencio es de estrella, tan lejano y sencillo.
                </Paragraph>
                <Paragraph>
                    Me gustas cuando callas porque estás como ausente.
Distante y dolorosa como si hubieras muerto.
Una palabra entonces, una sonrisa bastan.
Y estoy alegre, alegre de que no sea cierto.
                </Paragraph>
            </FlowDocument>
        </FlowDocumentScrollViewer>

 3.Paragraph

 

List: El elemento List permite definir una lista de elementos. Cada elemento debe estar dentro de un elemento ListItem, y los ListItem deben contener otro elemento como por ejemplo un Paragraph:


<FlowDocument>
                <Paragraph>
                    Cosas que debo comprar en el mercado:
                </Paragraph>
                <List MarkerStyle="Square">
                    <ListItem>
                        <Paragraph>Cervezas</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Queso</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Jamón</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Pan Tajado</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Leche</Paragraph>
                    </ListItem>
                </List>
                <List MarkerStyle="Decimal">
                    <ListItem>
                        <Paragraph>Papa</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Yuca</Paragraph>
                    </ListItem>
                    <ListItem>
                        <Paragraph>Arroz</Paragraph>
                    </ListItem>
                </List>
            </FlowDocument>

 4.List

El elemento List tiene la propiedad MarkerStyle, que permite configurar las viñetas, los valores posibles son:

Box, Circle, Decimal, Disc, LowerLatin, LowerRoman, None, UpperLatin, UpperRoman.

El ejemplo de cada uno en el orden de arriba:

 5.List2

 

Table:

El elemento Table es muy parecido al Table de HTML, para crear una tabla, se crea un elemento Table, que tendrá como hijo un elemento TableRowGroup, en el TableRowGroup habrá una colección de elementos TableRow, y los elementos TableRow tendrán a su vez una colección de elementos TableCell el cuál tendrá el contenido de una celda, como por ejemplo un elemento Paragraph, mm se ve complicado, con el siguiente ejemplo será más entendible:

<FlowDocument>
                <Table BorderBrush="Black">
                    <TableRowGroup Background="LightBlue">
                        <TableRow Background="SkyBlue">
                            <TableCell ColumnSpan="4" TextAlignment="Center">
                                <Paragraph FontSize="24pt" FontWeight="Bold">Ejemplo de una tabla</Paragraph>
                            </TableCell>
                        </TableRow>
                        <TableRow FontWeight="Bold" Foreground="Red">
                            <TableCell>
                                <Paragraph>Visitas</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>IP</Paragraph>
                            </TableCell>
                        </TableRow>
                        <TableRow Background="White">
                            <TableCell>
                                <Paragraph>100</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>127.0.0.1</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>lo que sea</Paragraph>
                            </TableCell>
                        </TableRow>
                        <TableRow Background="Gray">
                            <TableCell>
                                <Paragraph>100</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>127.0.0.1</Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>lo que sea</Paragraph>
                            </TableCell>
                        </TableRow>
                    </TableRowGroup>
                </Table>
            </FlowDocument>

 6.Table

 

Section:

El elemento Section es útil para agrupar otros elementos bloque, por ejemplo podemos tener una sección de muchos párrafos con un estilo y otra sección con otros estilos en el mismo documento:

<FlowDocument>
     <Section FontStyle="Italic">
                <Paragraph>
                    Me gustas cuando callas porque estás como ausente,
y me oyes desde lejos, y mi voz no te toca.
Parece que los ojos se te hubieran volado
y parece que un beso te cerrara la boca.
                </Paragraph>
     </Section>
     <Section Foreground="Red">
                <Paragraph>
                    Como todas las cosas están llenas de mi alma
emerges de las cosas, llena del alma mía.
Mariposa de sueño, te pareces a mi alma,
y te pareces a la palabra melancolía.
                </Paragraph>
</Section>
</FlowDocument>

 7.Section

 

BlockUIContainer:

Permite incorporar otros elementos UIElement, como un Button, un ListBox y otros.

<FlowDocument>
                <Section FontStyle="Italic">
                <Paragraph>
                    Me gustas cuando callas porque estás como ausente,
y me oyes desde lejos, y mi voz no te toca.
Parece que los ojos se te hubieran volado
y parece que un beso te cerrara la boca.
                </Paragraph>
                    </Section>
                <BlockUIContainer>
                    <Button>
                        Haz clic aquí para obtener más información
                    </Button>
                </BlockUIContainer>
            </FlowDocument>

 8.BlockUIContainer

Elementos en Línea (Contenido dinámico)

Los elementos dinámicos envuelven texto dentro de bloques, son usados para dar formato a los textos, como crear hipervínculos, aplicar propiedades como negrilla a una parte del texto, y otras.

Run: El elemento run, contiene texto normal, cuando no se crea ningún elemento dinámico, el elemento Run es aplicado implícitamente al texto

Bold, Italic y Underline

Estos elementos aplicados a un texto dan el formato de negrilla, Cursiva y Subrayado.

<FlowDocument>
                <Paragraph>Un ejemplo del los elementos
                    <Bold>Bold</Bold>,
                    <Italic>Italic</Italic> y
                    <Underline>Underline</Underline>
                   </Paragraph>
</FlowDocument>

 9.Bold

Hyperlink: Agrega un hipervínculo al texto:

        <FlowDocumentScrollViewer>
            <FlowDocument>
                <Paragraph>
                    Haciendo Pruebas, visita la siguiente
                    <Hyperlink NavigateUri="https://escarbandocodigo.wordpress.com/">Página</Hyperlink>
                </Paragraph>
            </FlowDocument>
       </FlowDocumentScrollViewer>

 10.HyperLink

LineBreak:

Provoca un salto de línea, este elemento no soporta contenido directo, por ejemplo:

<FlowDocument>
                <Paragraph>
                    El LineBreak sirve para<LineBreak/>
                    hacer saltos de línea
                    <LineBreak/>
                    como estos <LineBreak/>
                    😛
                </Paragraph>
</FlowDocument>

 11.LineBreak

Floater:

Permite crear una sección del documento que es paralela con el flujo principal del otro contenido, es útil para las imágenes:

<FlowDocument>
                <Paragraph>
                    Me gustas cuando callas porque estás como ausente,
y me oyes desde lejos, y mi voz no te toca.
Parece que los ojos se te hubieran volado
y parece que un beso te cerrara la boca.
                    <Floater FontFamily="TimesNewRoman" FontSize="12" Width="100" HorizontalAlignment="Left">
                        <Paragraph>
                            Como todas las cosas están llenas de mi alma
emerges de las cosas, llena del alma mía.
Mariposa de sueño, te pareces a mi alma,
y te pareces a la palabra melancolía.
                         </Paragraph>
                    </Floater>
                    <LineBreak/>
                    Me gustas cuando callas y estás como distante.
Y estás como quejándote, mariposa en arrullo.
Y me oyes desde lejos, y mi voz no te alcanza:
déjame que me calle con el silencio tuyo.
                </Paragraph>
</FlowDocument>

 12.Floater

InlineUIContainer:

Permite insertar elementos UIElement, dentro del elemento dinámico, es parecido al BlockUIContainer:

<FlowDocument>
                <Paragraph>Un ejemplo del elemento
                    <InlineUIContainer>
                        <Button FontSize="14">InLineUIContainer</Button>
                    </InlineUIContainer>
                    </Paragraph>
</FlowDocument>

 13.InLineUIContainer

Contenedores Flow Documentos

Existen 3 tipos de contenedores para los flow documents, ya vimos el FlowDocumentScrollViewer, y este contenedor cuadra todo su contenido de acuerdo a su tamaño y agrega barras de desplazamiento, es el contenedor más sencillo, aunque este también permite Zoom, para añadir el Zoom al FlowDocumentScrollViewer, solo debemos dejar la propiedad de IsToolBarVisible a True:

<FlowDocumentScrollViewer IsToolBarVisible=»True»>

 14.FlowDocumentScrollViewerZoom

El FlowDocumentPageViewer automáticamente divide el contenido en páginas, el tamaño de la página es determinado por el tamaño del contenedor, incluye también un control para la paginación, y un elemento Slider para el Zoom:

 15.FlowDocumentPageViewer

El FlowDocumentReader es el contenedor que más opciones tiene. Nos permite cambiar las vistas para la paginación, adiciona barras de desplazamiento, columnas, una barra de búsqueda y  Zoom:

 16.FlowDocumentReader

Bien, ahora podemos crear nuestros propios Lectores de documentos, podemos importarlos y exportarlos o si es el caso imprimirlos.

Para finalizar les dejo como imagen, el preludio del Libro: El Elfo Oscuro – La Morada en un Flow Document para que visualicen las características:

17.Final

 

Referencias:

– Libro: MCTS Self-Paced Training Kit (Exam 70-502): Microsoft® .NET Framework 3.5—Windows® Presentation Foundation

4 pensamientos en “Usando y creando documentos en WPF (FlowDocument)

    • Hola, si es por diseñador:

      Si es por código:

      FlowDocument document = new FlowDocument();
      Image image = new Image();
      BitmapImage bimg = new BitmapImage();
      bimg.BeginInit();
      bimg.UriSource = new Uri(«c:\image.png», UriKind.Absolute);
      bimg.EndInit();
      image.Source = bimg;
      document.Blocks.Add(new BlockUIContainer(image));

Deseas comentar o sugerir algo?