views:

198

answers:

3

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?

+4  A: 

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

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: alt text

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

Ciemnl
Thank You. The problem is that Floater doesn't allow control over placement, and Figure insists on keeping everything on one page. I need a combination of the two.
Bear
By magazine-style flow I mean stories that continue on later pages with other content in between.
Bear
hmmm I don't know then, you could create your own custom floater-figure thing deriving from Inline and write the specialised code yourself... That would mean you would get custom functionality without having to rewrite the entire text displaying system
Ciemnl
That's exactly what I'm looking for - how to customize the floater-figure. As far as I can tell, there is no hook into the internal paginator that FlowDocument uses, so deriving from Inline won't let me control layout.
Bear
thats pretty annoying... The last thing I can think of is using a .Net reflector (http://www.red-gate.com/products/reflector) to see whats actually hapening. Apart from that I'm afraid I'm out of ideas for how to fix your problem!
Ciemnl
A: 

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.

Nir
Thank you, but the flexibility of Flow Document is vital for me. I need the document to be reflowable so that the user can adjust text size, etc.
Bear
A: 

We use Apache FOP, an open source XSL-FO implementation, to create these types of documents. It's actually written in Java but we use IKVM to run it on .NET. IKVM is an open source implementation of Java that runs on .NET. It works pretty nicely. FOP produces PDF, RTF, and several other formats.

The downside is you'll need to learn XSL-FO, but it's not difficult if you're used to old school HTML.

http://xmlgraphics.apache.org/fop/

http://www.ikvm.net/

http://www.ikvm.net/uses.html

http://www.w3schools.com/xslfo/default.asp

Jeremy
I don't need to create the documents (some of them are actually originally PDFs) but rather display them in a reflowable manner.
Bear