# Sections, Pages, Headers, and Footers

> Add landscape sections, chapter headers, page columns and borders in the WPF TextControl, open Page Setup in code and turn pages into BitmapImage thumbnails.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Document Processing > Sections, Pages, Headers, and Footers
- **9333 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/sections-headers/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/sections-headers/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/sections-headers/llms-full.txt

---

Page layout in a WPF document editor comes from three building blocks: sections, which carry the page size, orientation and margins, the headers and footers of each section, and the pages that TX Text Control formats from them. The WPF `TextControl` shows all three as the user will see them on paper. From the code-behind of your window, you insert sections, add headers and footers with page numbers, react when the user edits a header and read the formatted pages.

The handlers below belong in *MainWindow.xaml.cs* of the application from [Create Your First WPF Application](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/document-editor/first-application/llms-full.txt), whose `TextControl` is named `textControl1` in *MainWindow.xaml*. [Creating Documents](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/creating/llms-full.txt) sets the page size and margins of a new document.

*MainWindow.xaml.cs* needs these `using` directives:

```csharp
using System.Text;
using System.Windows;
using TXTextControl;
```

### How Sections, Headers and Footers Fit Together

- **Sections** divide a document into parts with their own page size, margins, orientation, page columns and page borders, numbered from 1. [WPF.TextControl.Sections](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/sections-property/llms-full.txt) returns them, and [Section.Format](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/section/format-property/llms-full.txt) holds the page settings of a section. [What a Section Is](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/sections/#what-a-section-is) in Sections and Page Layout explains section breaks and what a new section inherits.
- **Headers and footers** are [HeaderFooter](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfooter/llms-full.txt) objects with a `Selection`, paragraphs, tables and images of their own, per section and by type. [How Headers and Footers Work](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/headers-footers/#how-headers-and-footers-work) in Headers and Footers describes the types and how the headers of consecutive sections are connected.
- **Pages** are the result of formatting. A section can span several pages, and a page can hold several sections. In page view, [GetPages](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/getpages-property/llms-full.txt) returns them as [Page](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/llms-full.txt) objects.

[SectionFormatDialog](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/sectionformatdialog-method/llms-full.txt) opens the **Page Setup** dialog box, in which users set these values themselves. Its parameter selects the tab: 0 for margins and paper, 1 for headers and footers, 2 for columns and 3 for page borders.

![The Page Setup dialog box with the Headers and Footers tab open and the Header list offering None, All sections equal and All sections different.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/page-setup-headers-footers.7b859779.webp)

`textControl1.SectionFormatDialog(1)` opens it with the **Headers and Footers** tab shown above. [Headers and Footers](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/headers-footers/llms-full.txt) and [Sections and Page Layout](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/sections/llms-full.txt) in the Document Editor section show the ribbon commands for the same settings.

### Insert a Section in Landscape Orientation

[SectionCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectioncollection/add-method/llms-full.txt) inserts a section break at the input position and returns `true` on success. A [SectionBreakKind](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionbreakkind/enumeration/llms-full.txt) value decides where the new section starts: `BeginAtNewPage` on the next page, `BeginAtNewLine` on the next line. The following `Click` handler of a button writes a report whose middle section is in landscape orientation:

```csharp
private void LandscapeSection_Click(object sender, RoutedEventArgs e)
{
    textControl1.Text = "";
    textControl1.Selection.Text = "Quarterly Report\r\nThis part is in portrait orientation.";

    // Section 2 begins on a new page and is turned to landscape
    textControl1.Sections.Add(SectionBreakKind.BeginAtNewPage);
    textControl1.Selection.Text = "This part has room for a wide table.";
    textControl1.Sections[2].Format.Landscape = true;

    // Section 3 inherits landscape from section 2, so turn it back
    textControl1.Sections.Add(SectionBreakKind.BeginAtNewPage);
    textControl1.Selection.Text = "The report continues in portrait orientation.";
    textControl1.Sections[3].Format.Landscape = false;
}
```

The code works as follows:

- The text written after each `Add` goes into the new section.
- `textControl1.Sections[2]` returns a section by its number through the [indexer](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectioncollection/item-property/llms-full.txt), and [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectioncollection/getitem-method/llms-full.txt) returns the section with the input position.
- [SectionFormat.Landscape](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/landscape-property/llms-full.txt) turns the pages. [Format a Section](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/sections/#format-a-section) in Sections and Page Layout lists the other properties of `SectionFormat`.

Page sizes and margins use the unit of [PageUnit](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/pageunit-property/llms-full.txt); column widths, lines and page borders use twips, 1/1440 inch.

### Add a Footer With Page Numbers

Page numbers are [PageNumberField](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagenumberfield/llms-full.txt) objects, which can only be placed in headers and footers through [HeaderFooter.PageNumberFields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfooter/pagenumberfields-property/llms-full.txt). [Add Page Numbers and Edit a Header From Code](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/headers-footers/#add-page-numbers-and-edit-a-header-from-code) in Headers and Footers adds a footer with "Page x of y" to a section and explains the page number fields and the distance of the footer from the page edge.

Headers and footers can also be added to the whole document with [WPF.TextControl.HeadersAndFooters](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/headersandfooters-property/llms-full.txt): one added there goes to the first section, and the other sections receive ones that are connected to it. [HeaderFooterCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfootercollection/add-method/llms-full.txt) and [Remove](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfootercollection/remove-method/llms-full.txt) take several [HeaderFooterType](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfootertype/enumeration/llms-full.txt) values combined with `|`, such as `HeaderFooterType.Header | HeaderFooterType.Footer`.

### Give a Section Its Own Header

Headers of consecutive sections are connected and show the same content. Set [ConnectedToPrevious](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfooter/connectedtoprevious-property/llms-full.txt) to `false` on the header of a section before you give it text of its own:

```csharp
private void ChapterHeaders_Click(object sender, RoutedEventArgs e)
{
    textControl1.Text = "";
    textControl1.Selection.Text = "Chapter 1\r\nThe first chapter.";
    textControl1.Sections.Add(SectionBreakKind.BeginAtNewPage);
    textControl1.Selection.Text = "Chapter 2\r\nThe second chapter.";

    textControl1.HeadersAndFooters.Add(HeaderFooterType.Header);

    // With several sections, get the headers from the sections
    HeaderFooter header1 = textControl1.Sections[1].HeadersAndFooters.GetItem(HeaderFooterType.Header);
    HeaderFooter header2 = textControl1.Sections[2].HeadersAndFooters.GetItem(HeaderFooterType.Header);

    header2.ConnectedToPrevious = false;

    header1.Selection.Text = "Chapter 1";
    header2.Selection.Text = "Chapter 2";

    // Page numbers start again in section 2
    textControl1.Sections[2].Format.RestartPageNumbering = true;
}
```

In a document with several sections, most collections of a `HeaderFooter` that you get from the document's collection are `null`, so take headers and footers from `Section.HeadersAndFooters`. A restarted section begins with the [StartNumber](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagenumberfield/startnumber-property/llms-full.txt) of its page number field.

### Set Page Columns and Page Borders

Page columns belong to a section. A section that begins on a new line changes the number of columns without a page break, so a heading can span the full width of the page while the text below it runs in two columns:

![A page of the TX Text Control demo document whose text runs in two page columns, with the overview and table of contents on the left and the form fields and footnotes sections on the right.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/two-page-columns.747e3a05.webp)

The following `Click` handler writes a heading, adds a two-column section below it on the same page and puts a border around the pages:

```csharp
private void Columns_Click(object sender, RoutedEventArgs e)
{
    textControl1.Text = "";
    textControl1.Selection.Text = "Newsletter\r\n";

    // A new section on the same page, in two columns 0.5 inch apart
    textControl1.Sections.Add(SectionBreakKind.BeginAtNewLine);

    SectionFormat twoColumns = new SectionFormat(2, 720);
    twoColumns.ColumnLineWidth = 10;
    twoColumns.ColumnLineColor = System.Drawing.Color.Gray;
    textControl1.Sections.GetItem().Format = twoColumns;

    textControl1.Selection.Text = "The text of this section flows from the first column into the second.";

    // A border 0.5 inch from the edge of each page, except the first page of the section
    PageBorder border = new PageBorder(20, 720, System.Drawing.Color.DarkBlue);
    border.OmitFirstPage = true;
    textControl1.Sections[1].Format.PageBorder = border;
}
```

The code works as follows:

- The [SectionFormat constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/constructor/llms-full.txt) with a number of columns and a distance in twips creates columns of equal width, calculated from the page size. Another overload takes an array of widths and an array of distances, for columns of different widths. [Columns](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/columns-property/llms-full.txt) is 1 by default. [ColumnWidths](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/columnwidths-property/llms-full.txt) and [ColumnDistances](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/columndistances-property/llms-full.txt) are read only, so other widths and distances need a new `SectionFormat`.
- [ColumnLineWidth](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/columnlinewidth-property/llms-full.txt) draws a line of that width in twips between the columns; the default, 0, draws none. [ColumnLineColor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/columnlinecolor-property/llms-full.txt) is a `System.Drawing.Color`, like the other colors of a document.
- [Section.Format](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/section/format-property/llms-full.txt) takes the new format for the section with the input position, which `Sections.GetItem()` returns.
- The [PageBorder constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pageborder/constructor/llms-full.txt) takes one line width in twips, one distance from the edge of the page and one color for all four lines. [OmitFirstPage](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pageborder/omitfirstpage-property/llms-full.txt) skips the first page of the section, `FirstPageOnly` draws the border on that page only, and [MeasureFromText](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pageborder/measurefromtext-property/llms-full.txt) measures the distances from the text instead of the edge. [SectionFormat.PageBorder](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/pageborder-property/llms-full.txt) gives the border to a section.

Each line of a [PageBorder](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pageborder/llms-full.txt) can also be set on its own, with properties such as `TopLineWidth`, `LeftLineColor` and `BottomDistance`.

#### Columns of Different Widths

A narrow sidebar column beside a wide text column needs the second `SectionFormat` constructor, which takes the number of columns, an array with one width per column and an array with one distance fewer. All values are twips. The widths and the distances together must not be wider than the text area of the page, which is the page width less the left and the right margin; otherwise the constructor throws an exception. So when you choose the first width, the second is what is left:

```text
second width = page width - left margin - right margin - first width - distance
```

The page size and the margins of a section are not in twips, but in the unit of [PageUnit](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/pageunit-property/llms-full.txt): `Millimeter`, `CentiInch` (1/100 inch), `StandardWPF` (1/96 inch) or `Twips`. The following method converts them before it calculates, and adds a section with two columns below the input position:

```csharp
// Twips per unit of the current PageUnit
private double TwipsPerPageUnit()
{
    switch (textControl1.PageUnit.ToString())
    {
        case "Millimeter": return 1440 / 25.4;
        case "CentiInch": return 14.4;
        case "StandardWPF": return 15;
        default: return 1; // Twips
    }
}

private void InsertColumns(int firstColumnWidth, int columnDistance)
{
    // A new section on the same page
    textControl1.Sections.Add(SectionBreakKind.BeginAtNewLine);
    SectionFormat current = textControl1.Sections.GetItem().Format;

    // PageSize is always given in portrait orientation
    double pageWidth = current.Landscape ? current.PageSize.Height : current.PageSize.Width;
    double factor = TwipsPerPageUnit();

    int textWidth = (int)((pageWidth - current.PageMargins.Left - current.PageMargins.Right) * factor);
    int secondColumnWidth = textWidth - firstColumnWidth - columnDistance;

    textControl1.Sections.GetItem().Format = new SectionFormat(
        2,
        new int[] { firstColumnWidth, secondColumnWidth },
        new int[] { columnDistance });
}
```

A call such as `InsertColumns(2880, 360)` gives the new section a first column of 2 inches and a gap of a quarter inch; the second column takes the rest of the line.

The code works as follows:

- [SectionFormat.PageSize](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/sectionformat/pagesize-property/llms-full.txt) is a `System.Drawing.Size` whose width and height are always those of the portrait page, so a landscape section, detected with `Landscape`, takes the height as its width.
- [PageMargins.Left](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagemargins/left-property/llms-full.txt) and [PageMargins.Right](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagemargins/right-property/llms-full.txt) are `double` values in the same unit as the page size. Multiplied by the factor, the text width is in twips, like the column widths.
- The constructor with arrays sets `EqualColumnWidth` to `false`. The `columnWidths` parameter must have exactly one element per column, and `columnDistances` one element fewer.
- `PageUnit.ToString()` returns the name of the current value, one of the four listed above. If your application sets `PageUnit` to one value at startup, a constant factor does the same.

### Remove All Section Breaks

Documents from Word often consist of several sections with their own page formats and headers. Removing the section breaks gives such a document one layout. The following handler loads a document and removes the break at the start of every section after the first, following the blog article [How to Delete All Section Breaks in a DOCX Document using C#](https://www.textcontrol.com/blog/2023/11/21/how-to-delete-all-section-breaks-in-a-docx-document-using-csharp/), which is written for Windows Forms:

```csharp
private void RemoveSections_Click(object sender, RoutedEventArgs e)
{
    textControl1.Load("report.docx", StreamType.WordprocessingML);

    // Sections.Count goes down with each removed break
    for (int section = 2; section <= textControl1.Sections.Count;)
    {
        // The input position in front of the break that starts the section
        textControl1.Select(textControl1.Sections[section].Start - 2, 0);

        // Insert a paragraph, select its end and delete it together with the break
        textControl1.Selection.Text = "\r\n";
        textControl1.Selection.Length = 1;
        textControl1.Selection.Text = "";
    }
}
```

[Section.Start](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/section/start-property/llms-full.txt) is the one-based position of the first character of a section. The loop doesn't count up, because each removed break lowers `Sections.Count` until a single section remains. The document then has one page orientation, one set of margins and one set of headers and footers.

### React When the User Edits a Header

A header or footer is *activated* when it receives the input position; the user then types in it instead of the main text. [Set Up the Editing Behavior in XAML](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/headers-footers/#set-up-the-editing-behavior-in-xaml) in Headers and Footers sets whether a click or a double-click activates it and handles the `HeaderFooterActivated` and `HeaderFooterDeactivated` events, and [HeaderFooter.Activate](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfooter/activate-method/llms-full.txt) and [Deactivate](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/headerfooter/deactivate-method/llms-full.txt) do the same in code; both return `true` on success.

### Work With the Pages of a Document

[Pages](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/pages-property/llms-full.txt) is the number of pages, and `GetPages` returns a [PageCollection](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagecollection/llms-full.txt) whose indexer takes a page number from 1. The collection exists only while [ViewMode](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/viewmode-property/llms-full.txt) is `ViewMode.PageView`; in the other views, `GetPages` returns `null`. Each `Page` has read-only properties, among them [Number](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/number-property/llms-full.txt), [Section](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/section-property/llms-full.txt), [Start](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/start-property/llms-full.txt), [Length](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/length-property/llms-full.txt), [Header](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/header-property/llms-full.txt) and [Footer](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/footer-property/llms-full.txt). The following handler lists them in a `TextBlock` named `statusText`:

```csharp
private void DescribePages_Click(object sender, RoutedEventArgs e)
{
    StringBuilder report = new StringBuilder();
    report.AppendLine($"{textControl1.Pages} pages in {textControl1.Sections.Count} sections");

    foreach (TXTextControl.Page page in textControl1.GetPages())
    {
        string header = page.Header == null ? "no header" : page.Header.Type.ToString();
        report.AppendLine($"Page {page.Number}: section {page.Section}, characters {page.Start} to {page.Start + page.Length - 1}, {header}");
    }

    statusText.Text = report.ToString();
}
```

`TXTextControl.Page` is written in full, because the Visual Studio template imports `System.Windows.Controls`, which has a `Page` class of its own. [InputPosition.Page](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputposition/page-property/llms-full.txt) is the page with the input position in page view, and [Page.Select](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/select-method/llms-full.txt) selects the text of a page without its header and footer.

#### Render a Page as an Image

[Page.GetImage](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/getimage-method/llms-full.txt) renders a page for thumbnails, previews or an export. Its overloads return a `System.Drawing.Bitmap`, a `System.Drawing.Imaging.Metafile` or a string in SVG format. Because two of them use types of the *System.Drawing.Common* library, a .NET WPF project can't call any `GetImage` overload until it has that package; the compiler otherwise reports error CS0012, "The type 'Bitmap' is defined in an assembly that is not referenced". Install the NuGet package [System.Drawing.Common](https://www.nuget.org/packages/System.Drawing.Common), as [Printing](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/printing/#prepare-the-project-for-printdocument) does for `PrintDocument`:

```bash
dotnet add package System.Drawing.Common
```

The following handler shows a thumbnail of the first page in an `Image` control named `thumbnailImage` of the window. A WPF `Image` takes a `BitmapSource`, so the bitmap is saved as PNG into a stream and loaded as a `BitmapImage` from `System.Windows.Media.Imaging`:

```csharp
private void ThumbnailButton_Click(object sender, RoutedEventArgs e)
{
    PageCollection pages = textControl1.GetPages();

    // 20 percent of the original size, with headers, footers and main text
    using (System.Drawing.Bitmap thumbnail = pages[1].GetImage(20, TXTextControl.Page.PageContent.All))
    using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
    {
        // Convert the System.Drawing bitmap into a WPF image source
        thumbnail.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
        stream.Position = 0;

        BitmapImage source = new BitmapImage();
        source.BeginInit();
        source.CacheOption = BitmapCacheOption.OnLoad;
        source.StreamSource = stream;
        source.EndInit();

        thumbnailImage.Source = source;
    }
}
```

The code works as follows:

- The indexer of the [PageCollection](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagecollection/llms-full.txt) takes a page number from 1.
- `GetImage(int, PageContent)` returns a bitmap in screen resolution, scaled by the zoom factor in percent. The values of [PageContent](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/pagecontent/enumeration/llms-full.txt), written as `Page.PageContent` in code, select the parts of the page: `Background`, `HeadersAndFooters` and `MainText`, and `All` for these three.
- `BitmapCacheOption.OnLoad` reads the stream completely in `EndInit`, so the stream and the bitmap can be disposed when the handler ends.

To export the pages as SVG files, which stay sharp at any size, call the overload with a maximum resolution for embedded pixel images. `File` needs `using System.IO;`, which WPF projects don't import by default:

```csharp
private void SaveSvgButton_Click(object sender, RoutedEventArgs e)
{
    foreach (TXTextControl.Page page in textControl1.GetPages())
    {
        // Images of the page are embedded as PNG with at most 150 dpi
        string svg = page.GetImage(TXTextControl.Page.PageContent.All, 150);
        File.WriteAllText($"page-{page.Number}.svg", svg);
    }
}
```

The blog article [Convert MS Word DOCX to SVG in .NET C#](https://www.textcontrol.com/blog/2024/12/30/convert-ms-word-docx-to-svg-in-net-csharp/) shows what the SVG contains.

#### Save the Pages as a Multipage TIFF

The pages of a document can also be saved as one TIFF file with a frame for each page. `GetImage` renders each page as a bitmap, and the TIFF encoder of *System.Drawing.Common* adds the bitmaps to the file as frames. The handler needs `using System.Drawing.Imaging;` and `using System.Linq;` at the top of *MainWindow.xaml.cs*:

```csharp
private void SaveTiffButton_Click(object sender, RoutedEventArgs e)
{
    // The TIFF encoder of System.Drawing
    ImageCodecInfo tiffCodec = ImageCodecInfo.GetImageEncoders()
        .First(codec => codec.MimeType == "image/tiff");

    using (EncoderParameters parameters = new EncoderParameters(2))
    {
        parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression,
            (long)EncoderValue.CompressionLZW);

        System.Drawing.Bitmap firstPage = null;

        foreach (TXTextControl.Page page in textControl1.GetPages())
        {
            // 100 percent, with headers, footers and main text
            System.Drawing.Bitmap bitmap = page.GetImage(100, TXTextControl.Page.PageContent.All);

            if (firstPage == null)
            {
                // The first page creates the file
                firstPage = bitmap;
                parameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag,
                    (long)EncoderValue.MultiFrame);
                firstPage.Save("document.tif", tiffCodec, parameters);
            }
            else
            {
                // Each further page is a new frame of the file
                parameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag,
                    (long)EncoderValue.FrameDimensionPage);
                firstPage.SaveAdd(bitmap, parameters);
                bitmap.Dispose();
            }
        }

        if (firstPage != null)
        {
            // Close the file
            parameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag,
                (long)EncoderValue.Flush);
            firstPage.SaveAdd(parameters);
            firstPage.Dispose();
        }
    }
}
```

The first bitmap is saved with `EncoderValue.MultiFrame` and creates the file; every further page is appended with `SaveAdd` and `FrameDimensionPage`, and `Flush` closes the file. The bitmaps are in screen resolution, scaled by the zoom factor in percent. `Encoder` is written with its namespace because `System.Text` has an `Encoder` class as well.

#### Remove Empty Pages

Documents assembled from several parts, or edited by users after they were created, can end up with pages that hold nothing but a page break or a section break. Such a page has a [Length](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/length-property/llms-full.txt) of 1, because the length counts the break at the end of the page. The following handler deletes these breaks:

```csharp
private void RemoveEmptyPagesButton_Click(object sender, RoutedEventArgs e)
{
    PageCollection pages = textControl1.GetPages();

    // From the last page to the first, so that the positions of earlier pages stay valid
    for (int number = pages.Count; number >= 1; number--)
    {
        TXTextControl.Page page = pages[number];

        // A page that holds nothing but its page or section break
        if (page.Length == 1)
        {
            // Page.Start counts from 1, text positions from 0
            textControl1.Select(page.Start - 1, 1);
            textControl1.Selection.Text = "";
        }
    }
}
```

[Page.Start](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/page/start-property/llms-full.txt) is the one-based number of the first character of the page, so `Start - 1` is the text position of the break. `Page.Select` doesn't help here, because it leaves out the page break characters. `RemoveEmptyPagesButton_Click` doesn't call `GetImage` and compiles without *System.Drawing.Common*.

### Next Steps

- [Headers and Footers](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/headers-footers/llms-full.txt): add headers and footers from the ribbon.
- [Sections and Page Layout](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/sections/llms-full.txt): page setup and section breaks in the user interface.
- [Fields and Subtext Parts](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/fields/llms-full.txt): other fields of a document.
- [Printing](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/printing/llms-full.txt): print the pages of a document.

---

## Nearby

- **Previous:** [Charts and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/charts-barcodes/llms-full.txt)
- **Next:** [Fields and Subtext Parts](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/fields/llms-full.txt)
