Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are my options for document layout in WPF?

Using WPF's FlowDocument, I have run in to a number of situations where I need more control over the layout of the document, from simple things (page headers and footers) to more complex (footnotes, magazine style story flow) to even more complex (literary texts with critical apparatus - one of my actual requirements).

However, as far as I can tell, my only options are:

A. Use FlowDocument and lose all control over layout.

B. Write everything from scratch using TextFormatter.

A is not an option for me, and B requires implementing dozens of methods, and more importantly, the loss of the power of FlowDocument and its associated Viewers.

My question is:

Is there any alternative that will allow me to leverage the power of FlowDocument, which covers 90% of my layout needs, and only write the code necessary to implement the other 10%?

EDIT: The reflowable aspect of the FlowDocument is crucial for me. I understand that I am asking for both reflowable content and precise control over layout, which are somewhat contradictory. However, I know that it can be done - I wrote a bare bones implementation using TextFormatter that accomplishes what I want, but I would MUCH rather use FlowDocument with some kind of extension to avoid reimplementing every feature.

EDIT 2: It seems that what I am really after is a hook into FlowDocument's internal paginator, so that I can give it instructions for laying out a custom class. Is there any way to do that?

like image 753
yclevine Avatar asked Jun 30 '10 15:06

yclevine


2 Answers

The text system in WPF is primarily designed for playing around with text for use in UIs, not for producing complex documents with footnotes and headers etc. However, the framework has been written so that if you want to add custom functionality, you can.

First problem: Footnotes and stuff that is in-line with the text. WPF provides 2 classes to put UIElements in text: InlineUIContainer and BlockUIContainer. I would consider writing your own custom control that is specially designed to have the behaviour of a footnote or something similar and put it in one of those two classes. I found this handy-dandy relationship chart on MSDN if you need more info on what accepts what (links are at the bottom of the page)

alt text
(source: microsoft.com)

I’m not completely sure what you mean by “magazine style story flow”. 'FlowDocument' will automatically arrange Block-derived classes (anything in blue on the above chart) into the available space and you can make the text ‘flow’ around objects using the Floater and Figure inline elements. You could also use Figure and Floater for your headers and footers feature.

Here is some example code:

    <FlowDocumentScrollViewer>
        <FlowDocument>
            <Paragraph>
                5 green bottles standing on the wall,
                5 green bottles standing on the wall, 
                and if one green bottle was to accidentally fall,
                there would be 4 green bottles standing on the wall;
            </Paragraph>
            <Paragraph>
                4 green bottles standing on the wall,
                4 green bottles standing on the wall, 
                <Floater HorizontalAlignment="Left" Width="250">
                    <BlockUIContainer>
                        <Button>This button is in a Floater</Button>
                    </BlockUIContainer>
                </Floater> 
                and if one green bottle was to accidentally fall,
                there would be 3 green bottles standing on the wall;
            </Paragraph>
            <Paragraph>
                3 green bottles standing on the wall,
                3 green bottles standing on the wall, 
                and if one green bottle was to accidentally fall,
                there would be 2 green bottles standing on the wall;
            </Paragraph>

            <Paragraph>
                2 green bottles standing on the wall,
                2 green bottles standing on the wall,
                and if one green bottle was to accidentally fall,
                <InlineUIContainer>
                    <Button>This Button is inline</Button>
                </InlineUIContainer> 
                there would be 1 green bottle standing on the wall...
            </Paragraph>
        </FlowDocument>
    </FlowDocumentScrollViewer>

You can replace the Buttons with your own custom controls (eg. the inline button with your footnote thang)

This code makes this: DesignerView

I hope that helps! I don't know exactly what you are trying to do but I would think that you could still use FlowDocument and just use the large amount of text manipulating equipment provided with WPF and if you do need extra functionality/ layout options create a new class inheriting Block or Inlineor whatever and write the extra stuff in there to take advantage of all the work .net can do for you. If you need more information you can read more about text stuff in WPF on MSDN:

Extra long article about how to use FlowDocument

The text content model used in WPF (where I got the image from)

Enjoy yourself :)

like image 79
Ed Ayers Avatar answered Oct 13 '22 21:10

Ed Ayers


The answer is actually simple: FixedDocument

Now, with FixedDocument you will lose the on-screen flexibility of the FlowDocument but you will gain support for just about everything and DocumentViewer is a great viewer for fixed documents.

Also, you can save Fixed documents to XPS and view them outside you app.

This code shows how to take a FLowDocument and convert it to a FixedDocument with headers, footers and margin. I think it shouldn't be too difficult to adapt this code to also support footnotes.

like image 43
Nir Avatar answered Oct 13 '22 20:10

Nir