TX Text Control .NET for WPF

Create a Document Programmatically

Topic

A WPF application often produces documents that nobody types: a report built from figures, a confirmation or a cover letter. ServerTextControl builds such a document in code with the same building blocks a user has in the editor, formatted paragraphs, a table, an image and a page header, without touching the document in the editor. In a few steps, a button of your window creates a short quarterly report, writes it to a DOCX file and opens it in the TextControl of the window.

Prerequisites

  • The application from Create Your First WPF Application, with a TextControl named textControl1 in MainWindow.xaml.
  • An image file named logo.png in the project. In its properties, set Build Action to Content and Copy to Output Directory to Copy if newer, so that the file is next to the application when it runs.

Add a button to the DockPanel of MainWindow.xaml, before the TextControl element, so that it docks above the editor:

<Button x:Name="createButton" DockPanel.Dock="Top" Content="Create Report"
        Click="createButton_Click" />

How Code Builds a Document

A ServerTextControl holds a document in memory and has no user interface. Your code writes into it at the current input position, the way typing does: its Selection sets the formatting of the next text and inserts it, and tables and images are inserted at the same position. Every insertion moves the input position behind the new content, so the document grows in the order in which the code runs.

The component itself is described in ServerTextControl in the Overview.

Build the Document

Replace the content of MainWindow.xaml.cs with the following code, keeping the namespace of your project:

using System.Windows;
using TXTextControl;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void createButton_Click(object sender, RoutedEventArgs e)
    {
        byte[] document;

        using (ServerTextControl tx = new ServerTextControl())
        {
            // Initialize the new instance before using it
            tx.Create();

            // Title: Arial, 24 pt, bold, centered
            tx.Selection.FontName = "Arial";
            tx.Selection.FontSize = 480; // 480 twips = 24 pt
            tx.Selection.Bold = true;
            tx.Selection.ParagraphFormat = new ParagraphFormat()
            {
                Alignment = TXTextControl.HorizontalAlignment.Center
            };
            tx.Selection.Text = "Quarterly Report\r\n";

            // Body text: 12 pt, not bold, left-aligned
            tx.Selection.FontSize = 240; // 240 twips = 12 pt
            tx.Selection.Bold = false;
            tx.Selection.ParagraphFormat = new ParagraphFormat()
            {
                Alignment = TXTextControl.HorizontalAlignment.Left
            };
            tx.Selection.Text = "Sales by region for the second quarter.\r\n";

            // A table of 4 rows and 3 columns with the ID 10
            tx.Tables.Add(4, 3, 10);
            TXTextControl.Table table = tx.Tables.GetItem(10);

            TXTextControl.TableRow headerRow = table.Rows.GetItem(1);
            headerRow.IsHeader = true;
            headerRow.CellFormat = new TableCellFormat()
            {
                BackColor = System.Drawing.Color.LightSteelBlue
            };

            foreach (TXTextControl.TableCell cell in table.Cells)
            {
                cell.Text = $"R{cell.Row} C{cell.Column}";
            }

            // Text and a logo below the table
            tx.Selection.Text = "Source: sales department.\r\n";

            TXTextControl.Image logo = new TXTextControl.Image("logo.png", 4); // 4 = PNG
            tx.Images.Add(logo, -1); // -1 = at the input position

            // A header that repeats on every page
            tx.HeadersAndFooters.Add(HeaderFooterType.Header);
            HeaderFooter header = tx.HeadersAndFooters.GetItem(HeaderFooterType.Header);
            header.Selection.Text = "Sample Company Inc.";

            // A DOCX file, and a byte array for the editor
            tx.Save("report.docx", StreamType.WordprocessingML);
            tx.Save(out document, BinaryStreamType.InternalUnicodeFormat);
        }

        // Show the report in the editor of the window
        textControl1.Load(document, BinaryStreamType.InternalUnicodeFormat);
    }
}

What the Code Does

  • Initializing. Create has to be called before any other member of the ServerTextControl. The using statement releases the instance as soon as the report is saved.
  • Formatting text. FontName, FontSize and Bold set the character formatting, and ParagraphFormat with its Alignment the paragraph formatting. Both apply to the text that the next assignment to Selection.Text inserts. Font sizes are in twips, 20 twips per point, and \r\n ends a paragraph.
  • Qualified names. WPF has types of the same name: HorizontalAlignment in System.Windows and Image in System.Windows.Controls. Write TXTextControl.HorizontalAlignment and TXTextControl.Image in a window's code so that the compiler takes the TX Text Control types.
  • The table. Tables.Add inserts a table with an ID that you choose, and GetItem returns it by that ID. Rows count from 1. IsHeader turns the first row into a header row that repeats on each page, CellFormat with BackColor shades it, and TableCell.Text fills the cells. The colors of TX Text Control are System.Drawing.Color values, not WPF brushes. After the table is inserted, the input position is below it.
  • The image. The Image constructor takes a file name and the index of the image format, 4 for PNG. Images.Add with the position -1 places the image at the input position, inline with the text.
  • The header. HeadersAndFooters.Add creates the header, GetItem returns it, and the Selection of the HeaderFooter writes its text.
  • Saving and showing. Save writes report.docx into the output folder, and a second call copies the document into a byte array in the TX Text Control format. TextControl.Load opens that byte array in the editor.

Run the Application

Press F5 and click Create Report. The editor shows the centered title, the paragraph, the table with its shaded header row, the line below it and the logo. report.docx in the output folder, bin\Debug\net8.0-windows for a .NET 8 project, contains the same document and opens in Microsoft Word.

The header "Sample Company Inc." is part of the document, but the editor shows headers and footers only when its ViewMode is PageView. Set the attribute ViewMode="PageView" on the TextControl element in XAML to see it.

Build the Document in the Editor Instead

The TextControl of the window has the same Selection, Tables, Images and HeadersAndFooters members, so the calls also work on the document the user sees:

textControl1.Selection.FontSize = 480;
textControl1.Selection.Text = "Quarterly Report\r\n";
textControl1.Tables.Add(4, 3, 10);
textControl1.HeadersAndFooters.Add(HeaderFooterType.Header);

Call such code after WPF has loaded the TextControl, for example in its Loaded event or in a button handler, not in the constructor of the window. Control Initialization explains why. A ServerTextControl remains the better choice for documents that are not meant for editing: it builds them without touching the document the user works on.

Next Steps