TX Text Control .NET for WPF

WPF Layout and Resizing

Topic

The WPF TextControl takes the size its panel gives it, like any other control, and fills it with the document. Getting the layout right therefore comes down to the panel: a DockPanel for the editor and its bars, a Grid when the editor shares the window with other content, and a view mode that decides whether the text follows the width of the control or the size of a page. The sections below cover each of these for windows that resize.

How the Editor Gets Its Size

  • The panel decides. In a Grid cell or as the last child of a DockPanel, the TextControl stretches to the space left over and resizes with the window. Leave its Width and Height unset; Visual Studio adds both when you drop the control from the toolbox, and the tutorials remove them.
  • The editor scrolls itself. The template of the TextControl contains a ScrollViewer that shows the visible part of the document (see TextControlDocument). Don't put the control into another ScrollViewer or into a StackPanel, which give their children as much space as they ask for instead of the space of the window.
  • Scroll bars are dependency properties. HorizontalScrollBarVisibility and VerticalScrollBarVisibility take the System.Windows.Controls.ScrollBarVisibility values of WPF, such as Auto or Disabled.
  • The border is BorderThickness, a Thickness like that of other WPF controls.

Arrange the Editor and Its Bars in a DockPanel

A DockPanel places each child at the side named by DockPanel.Dock in the order of the XAML, and gives the last child the rest. The bars come first and the TextControl last:

<DockPanel>
    <WPF:ButtonBar x:Name="buttonBar1" DockPanel.Dock="Top" />
    <WPF:RulerBar x:Name="rulerBar1" DockPanel.Dock="Top" />
    <WPF:StatusBar x:Name="statusBar1" DockPanel.Dock="Bottom" />
    <WPF:RulerBar x:Name="rulerBar2" DockPanel.Dock="Left"
                  HorizontalAlignment="Left" VerticalAlignment="Stretch" />
    <WPF:TextControl x:Name="textControl1"
                     ButtonBar="buttonBar1"
                     RulerBar="rulerBar1"
                     VerticalRulerBar="rulerBar2"
                     StatusBar="statusBar1" />
</DockPanel>

The button bar and the horizontal ruler stack at the top in this order, the status bar spans the bottom, and the vertical ruler sits at the left of the editor. Because the status bar comes before the vertical ruler, it runs under the ruler across the full width. The second RulerBar shows a vertical scale because it is docked at the left and stretched vertically, and it works as the vertical ruler of the editor because VerticalRulerBar names it:

The Design view of a WPF window with the button bar, a horizontal and a vertical ruler, the page of the editor and the status bar with page, line and column numbers and a zoom slider.

The bars are connected to the editor by name, not by their place in the panel. Create Your First WPF Application builds this window with the toolbox, and Rulers and Status Bar describes the settings of the bars. In a ribbon window, the Ribbon is the first child, docked at the top; Connecting Ribbon Tabs in XAML shows it.

Place the Editor in a Grid

When the window holds more than the editor, such as a list of documents, a Grid divides it, and a GridSplitter lets the user move the border. The editor and its bars keep their DockPanel, which fills one cell of the grid:

<Window x:Class="MyWPFApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WPF="clr-namespace:TXTextControl.WPF;assembly=TXTextControl.WPF"
        Title="MainWindow" Height="600" Width="1000">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="220" MinWidth="120" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" MinWidth="300" />
        </Grid.ColumnDefinitions>

        <ListBox x:Name="documentList" Grid.Column="0" />

        <GridSplitter Grid.Column="1" Width="5"
                      HorizontalAlignment="Center" VerticalAlignment="Stretch" />

        <DockPanel Grid.Column="2">
            <WPF:ButtonBar x:Name="buttonBar1" DockPanel.Dock="Top" />
            <WPF:RulerBar x:Name="rulerBar1" DockPanel.Dock="Top" />
            <WPF:StatusBar x:Name="statusBar1" DockPanel.Dock="Bottom" />
            <WPF:RulerBar x:Name="rulerBar2" DockPanel.Dock="Left"
                          HorizontalAlignment="Left" VerticalAlignment="Stretch" />
            <WPF:TextControl x:Name="textControl1"
                             ViewMode="PageView"
                             ButtonBar="buttonBar1"
                             RulerBar="rulerBar1"
                             VerticalRulerBar="rulerBar2"
                             StatusBar="statusBar1" />
        </DockPanel>
    </Grid>
</Window>

The XAML works as follows:

  • The first column has a fixed start width and a minimum, the second holds the splitter, and the third, with Width="*", takes the rest of the window. MinWidth="300" keeps the editor usable when the user drags the splitter to the right.
  • The GridSplitter in its own Auto column resizes the columns on both sides of it.
  • The DockPanel in the third column arranges the editor and its bars as in the previous section. The vertical ruler is placed by the DockPanel, as in the samples of Text Control, rather than by a cell of the grid.

Run the application and drag the splitter: the editor, the rulers and the status bar follow the new width.

Let the Document Follow the Control

What happens to the text when the control changes its size depends on ViewMode:

ViewModeText is formattedSuits
PageViewAccording to the page size and margins; pages are shown with gaps on a background, headers and footers includedDocuments that are printed or exported
NormalAccording to the page size and margins, with scroll bars; headers and footers are not displayedEditing page-based documents without the page view
FloatingTextTo the width of the control, with a vertical scroll bar; page size and margins are ignoredNotes, messages and other text without pages
SimpleControlTo the width and height of the control; when the control is full, no more text can be typedSmall fields in a form

With PageView and Normal, the line breaks follow the page, so they stay the same when the window gets narrower. With FloatingText, the text is formatted to the width of the control, which changes with the window. ViewMode is a dependency property, so a style or a binding can set it. Viewing, Zooming, and Navigation covers the view modes and the zoom.

In SimpleControl mode, AutoControlSize can let the control grow or shrink with its text. It takes an AutoSize object whose AutoExpand and AutoShrink properties set the directions; the events VExpanded and HExpanded report that the control has expanded.

Show and Hide Parts of the Layout

The bars and sidebars are WPF elements. Setting the Visibility of a bar to Collapsed removes it from the layout, and the DockPanel gives its space to the editor; Rulers and Status Bar shows this and the check boxes of the ribbon that do the same for the user. A Sidebar, docked at a side of the DockPanel like a ruler, opens and closes through its IsShown property; Sidebar and Panels places sidebars in the window.

Next Steps