FlowDocuments, Images, and Text Wrapping

While working on a project, I had a requirement to display an image accompanied by text that wrapped around said image.  I knew right away that TextBlocks were not going to help me there.  I quickly set out to find something capable of flowing text; enter the FlowDocument.  Most of the samples I found discussed how to create large formatted documents and how to display them.  I was struggling to find a nice concise article on how to create a simple reusable UI snippet that incorporated wrapping text and didn’t require an actual file.  No longer will you have to suffer the same fate as I; for I am here to show you the light!  Feast your eyes upon the result:

image

First off, let’s start with the container to hold our nifty FlowDocument.  There are numerous options for displaying FlowDocuments: FlowDocumentReader, FlowDocumentScrollViewer, and FlowDocumentPageViewer.  We will be using FlowDocumentScrollViewer since it allows hiding of the default toolbar and is the easiest to configure to quickly display our fake document in a format that is desired.  Here is the definition for the FlowDocumentScrollViewer:

<FlowDocumentScrollViewer Focusable="False" IsToolBarVisible="False"
                          ScrollViewer.CanContentScroll="False"
                          ScrollViewer.HorizontalScrollBarVisibility
="Disabled"
                          ScrollViewer.VerticalScrollBarVisibility
="Disabled"
                          HorizontalAlignment="Stretch" VerticalAlignment="Center" />

This will set our FlowDocumentScrollViewer up so that it is purely for displaying our fake document and won’t get in the way of our UI.  No scrolling, no interaction.  Next we need to design our document layout: 

<FlowDocument>
    <Paragraph FontWeight="Normal" Foreground="WhiteSmoke" TextAlignment="Left">
        <Floater Width="48" HorizontalAlignment="Left" Margin="0,0,4,0" Padding="0">

           <BlockUIContainer>

                 <Image Source="file://c:/temp/bacon.png" Width="48" Height="34" />

           </BlockUIContainer> 
       </Floater><Run Text="The Baconator" FontSize="16" Foreground="WhiteSmoke" TextDecorations="Underline" /><LineBreak /><Run Text="Bacon ipsum dolor sit amet adipisicing t-bone sirloin filet mignon ribeye. Tenderloin ex strip steak, pork chop hamburger est." FontSize="12" Foreground="WhiteSmoke" />
    </Paragraph>
</FlowDocument>

There are some caveats to using FlowDocuments.  The one that you need to look out for most is that FlowDocuments are very literal, meaning it will display any white space you include in your xaml.  This is why the Run elements and LineBreaks are all on the same line because any spaces and/or line returns you place in there will be displayed in the output.  Also, by default FlowDocuments use Justify as their text alignment so if you don’t want your output getting spaced out then make sure you set your TextAlignment to Left on the Paragraph.

Obviously for discussion and sample purposes I used literal text in the flow document but you can easily replace the literal text with Bindings in the Runs (assuming using .NET 4.0) and the Image.  I hope you found this useful.  Here is the full xaml for the visual shown above.  Obviously you will need to tweak this to suit your needs but this should give you a great start.

  

<Border Background="#2B3346" BorderBrush="#212937" BorderThickness="1" Width="250" Height="100">

<FlowDocumentScrollViewer Focusable="False" IsToolBarVisible="False" ScrollViewer.CanContentScroll="False"

ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled"

HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin=”0,-5,0,0”>

<FlowDocumentScrollViewer.Document>

<FlowDocument>
<Paragraph FontWeight="Normal" Foreground="WhiteSmoke" TextAlignment="Left">
<Floater Width="48" HorizontalAlignment="Left" Margin="0,0,4,0" Padding="0">

<BlockUIContainer>

<Image Source="file://c:/temp/bacon.png" Width="48" Height="34" />

</BlockUIContainer>
</Floater><Run Text="The Baconator" FontSize="16" Foreground="WhiteSmoke" TextDecorations="Underline" /><LineBreak /><Run Text="Bacon ipsum dolor sit amet adipisicing t-bone sirloin filet mignon ribeye. Tenderloin ex strip steak, pork chop hamburger est." FontSize="12" Foreground="WhiteSmoke" />
</Paragraph>
</FlowDocument>

</FlowDocumentScrollViewer.Document>

</FlowDocumentScrollViewer> </Border>

Leave a Reply

Your email address will not be published. Required fields are marked *