WPF FAQ - Flow Content

Find answers for the most frequently asked questions
Expand All Collapse All

Let us say you have your application running in a folder called C:\MyApp. Then if you want to load a FlowDocumentContent.xaml from a folder called C:\Contentthen this is easily done by first defining a FlowDocumentReader in your app like so:

 [XAML]
              <FlowDocumentReader Name='myFlowDocument' ViewingMode='Scroll'  IsTwoPageViewEnabled='False' IsPageViewEnabled='False'>
              </FlowDocumentReader>

And load the xaml file as follows:

 [C#]
            	FileStream xamlFile = new FileStream(filePath, FileMode.Open, FileAccess.Read);
	// This will work, only if the top-level element in the document is FlowDocument
            	FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;

	this.myFlowDocument.Document = content;

            	xamlFile.Close();

But if you have references to sub-folders in your document. For example, if you are referring to images under this folder C:\Content\Images, then those images wouldn’t be found by the parser because the parser is executing with the application directory context whereas the document contents are in a different directory. To make this work, you can force a context on the parser as follows:

 [C#]
            	ParserContext context = new ParserContext();
            	context.BaseUri = new Uri(filePath, UriKind.Absolute);
            	FlowDocument content = XamlReader.Load(xamlFile, context) as FlowDocument;
Permalink

This example demonstrates how to save the contents of a FlowDocumentReader (represented by the ‘Document’ property) as an XAML file.

[XAML]

<FlowDocumentReader
Name='flowDocRdr'
IsFindEnabled='True'
IsPrintEnabled='True'
MinZoom='50' MaxZoom='1000'
Zoom='120' ZoomIncrement='5'
/>


To save the contents of the FlowDocumentReader to a file, open or create the file stream and use the ‘Save()’ method provided by the ‘XAMLWriter’ class to write the FlowDocument to the file stream.

[C#]

void SaveFlowDocumentReaderWithXAMLFile(string fileName)
{
// Open or create the output file.
FileStream xamlFile = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
// Save the contents of the FlowDocumentReader to the file stream that was just opened.
XamlWriter.Save(flowDocRdr.Document, xamlFile);

xamlFile.Close();
} 

Permalink

This example demonstrates how to parse an XAML file that contains a FlowDocument and display the loaded file in a FlowDocumentReader.

[XAML]

<FlowDocumentReader
  Name='flowDocRdr' 
  IsFindEnabled='True'  
  IsPrintEnabled='True'
  MinZoom='50' MaxZoom='1000'
  Zoom='120' ZoomIncrement='5'
/>

And write the following FlowDocument to the file stream :

[C#]

void LoadFlowDocumentReaderWithXAMLFile(string fileName)
{
    // Open the file that contains the FlowDocument...
    FileStream xamlFile = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    // and parse the file with the XamlReader.Load method.
    FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;
    // Finally, set the Document property to the FlowDocument object that was
    // parsed from the input file.
    flowDocRdr.Document = content;

    xamlFile.Close();
}
Permalink

A BlockUIContainer is a flow content element that allows UIElement to be hosted inside the flow content. This can be done as follows.

[XAML]

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

Figure and Floater are used to embed content in Flow Documents with placement properties that can be customized independent of the primary content flow. Figure or Floater elements are often used to highlight or accentuate portions of content to host supporting images or other content within the main content flow or to inject loosely related content such as advertisements.

The following example shows how to embed a Figure into a paragraph of text.

[XAML]

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

</FlowDocument>
Permalink

We can define three paragraphs under one section as follows.

In the following example, the section has a “Background” property value of Red, therefore the background color of the paragraphs is also red.

[XAML]

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

Permalink

This can be done as follows.

[C#]

public static class SerializationUtil
{
   static public T Clone(T source)
   {
      Debug.Assert(typeof(T).IsSerializable);

      IGenericFormatter formatter = new GenericBinaryFormatter(); 
      Stream stream = new MemoryStream(); 
      formatter.Serialize(stream,source);
      stream.Seek(0,SeekOrigin.Begin);

      T clone = formatter.Deserialize(stream);
      stream.Close(); 
      return clone;
   }
//Rest of SerializationUtil
}
Permalink

You can store a given document format using CreateSerializerWriter method as follows.

[C#]

// Create a SerializerProvider for accessing plug-in serializers.
SerializerProvider serializerProvider = new SerializerProvider();

// Locate the serializer that matches the fileName extension.
SerializerDescriptor selectedPlugIn = null;
foreach ( SerializerDescriptor serializerDescriptor in
                serializerProvider.InstalledSerializers )
{
    if ( serializerDescriptor.IsLoadable &&
         fileName.EndsWith(serializerDescriptor.DefaultFileExtension) )
    {   // The plug-in serializer and fileName extensions match.
        selectedPlugIn = serializerDescriptor;
        break; // foreach
}
}

// If a match for a plug-in serializer was found,
// use it to output and store the document.
if (selectedPlugIn != null)
{
    Stream package = File.Create(fileName);
    SerializerWriter serializerWriter =
        serializerProvider.CreateSerializerWriter(selectedPlugIn,
                                                  package);
    IDocumentPaginatorSource idoc =
        flowDocument as IDocumentPaginatorSource;
    serializerWriter.Write(idoc.DocumentPaginator, null);
    package.Close();
    return true;
}
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.