TX Text Control .NET for WPF

Value Converters

Topic

TX Text Control measures distances in twips, a twentieth of a point, and its InputFormat reports colors as System.Drawing.Color and list formats as enumeration values. WPF controls expect other types: text, double values in device-independent units, System.Windows.Media.Color, bool. Four value converters of the namespace TXTextControl.WPF translate between the two in a binding, so that a text box, a color swatch, a radio button or a slider can show and change the editor's values without code-behind.

ConverterFrom the editorTo the WPF controlTypical use
MeasureConverterint in twipsstring or double in another unitFont sizes, indents, paragraph distances
ColorConverterSystem.Drawing.ColorSystem.Windows.Media.ColorText and background colors
BooleanConverterAn enumeration value, int, char or bool?boolRadio buttons, check marks in menus, toggle buttons
LogarithmicConverterA number on a linear scaleA number on a logarithmic scaleA zoom slider

Each of them implements IValueConverter, and each converts in both directions: Convert for values from the editor, ConvertBack for values the user enters. When a value can't be converted, both return DependencyProperty.UnsetValue.

Declare a Converter

A converter is an object in the resources, created once and used by any number of bindings through its key. The window declares the prefix of TX Text Control and the converters in its resources:

<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="450" Width="800">
    <Window.Resources>
        <WPF:MeasureConverter x:Key="pointConv" Unit="Point" Decimals="1" />
        <WPF:MeasureConverter x:Key="cmConv" Unit="Centimeter" Decimals="2" ShowAllDecimals="True" />
        <WPF:ColorConverter x:Key="colorConv" />
        <WPF:BooleanConverter x:Key="boolConv" />
        <WPF:LogarithmicConverter x:Key="logConv"
                                  InputMinimum="10" InputCenter="100" InputMaximum="400"
                                  OutputMinimum="0" OutputMaximum="100" />
    </Window.Resources>
    <DockPanel>
        <!-- The controls of the following sections go here -->
        <WPF:TextControl x:Name="textControl1" />
    </DockPanel>
</Window>

A binding names the converter with Converter={StaticResource key}. To use the same converters in every window, declare them once in App.xaml or a resource dictionary, as Resource Dictionaries and Styling shows.

Show Measures in Points or Centimeters

MeasureConverter converts a value in twips into the unit that its Unit property names, and back:

UnitThe converted value is in
PointPoints, 1/72 inch
CentimeterCentimeters
MillimeterMillimeters
CentiInch1/100 inch
StandardWPF1/96 inch, the device-independent units of WPF
TwipsTwips, 1/1440 inch

The type of the target decides whether the result is a string or a double. Decimals sets the number of decimals, and ShowAllDecimals whether a string shows all of them: with three decimals, 15.5 becomes 15.500 when it is true and 15.5 when it is false.

The following text boxes show the font size at the input position in points and the space above the paragraph in centimeters. Typing a new value changes the selected text:

<ToolBar DockPanel.Dock="Top">
    <TextBox x:Name="fontSizeTextBox" Width="50"
             Text="{Binding ElementName=textControl1, Path=InputFormat.FontSize,
                            Converter={StaticResource pointConv}, Mode=TwoWay}" />
    <TextBox x:Name="topDistanceTextBox" Width="60"
             Text="{Binding ElementName=textControl1, Path=InputFormat.TopDistance,
                            Converter={StaticResource cmConv}, Mode=TwoWay}" />
</ToolBar>

InputFormat.FontSize and InputFormat.TopDistance are both in twips. A TextBox updates its source when it loses the focus, so the new size applies when the user leaves the box.

Show the Text Color

ColorConverter converts a System.Drawing.Color into a System.Windows.Media.Color, the type of the Color property of a WPF brush. The following swatch shows the color of the text at the input position:

<Rectangle Width="16" Height="16" Margin="4,0">
    <Rectangle.Fill>
        <SolidColorBrush Color="{Binding ElementName=textControl1, Path=InputFormat.TextColor,
                                         Converter={StaticResource colorConv}}" />
    </Rectangle.Fill>
</Rectangle>

InputFormat.TextColor and TextBackColor have the type System.Drawing.Color?. ConvertBack works as well, so a color picker whose selected color is a System.Windows.Media.Color can set the text color through a two-way binding.

Check a Radio Button for a List Format

BooleanConverter returns true when the converter parameter is the string representation of the value. With an enumeration property such as InputFormat.NumberedListFormat, each radio button names the value it stands for:

<RadioButton Content="1, 2, 3" GroupName="numberFormat" Focusable="False"
             IsChecked="{Binding ElementName=textControl1, Path=InputFormat.NumberedListFormat,
                                 Converter={StaticResource boolConv}, ConverterParameter=ArabicNumbers}" />
<RadioButton Content="a, b, c" GroupName="numberFormat" Focusable="False"
             IsChecked="{Binding ElementName=textControl1, Path=InputFormat.NumberedListFormat,
                                 Converter={StaticResource boolConv}, ConverterParameter=Letters}" />

The values are those of the NumberFormat enumeration, such as ArabicNumbers, Letters, CapitalLetters, RomanNumbers and SmallRomanNumbers. When a radio button is checked, ConvertBack returns its parameter, and the list format of the selected paragraphs changes. When it is unchecked, ConvertBack returns DependencyProperty.UnsetValue, so that only the checked button of the group sets a value.

The converter supports System.Enum, int, int?, bool?, char and char?. For a bool? source, such as InputFormat.Bold, it converts to bool without a parameter, which suits a MenuItem with IsCheckable="True".

Zoom With a Slider

A zoom slider that runs from 10 to 400 percent in a straight line leaves little room for the values around 100 percent that users choose most. LogarithmicConverter maps the linear range of the slider to a logarithmic one:

<Slider x:Name="zoomSlider" DockPanel.Dock="Bottom" Minimum="0" Maximum="100"
        Value="{Binding ElementName=textControl1, Path=ZoomFactor,
                        Converter={StaticResource logConv}}" />

The resource defines the ranges:

ZoomFactor is a dependency property, and the Value of a slider binds in both directions by default, so moving the slider zooms the document without a handler.

When No Converter Fits

For other conversions, write a class that implements System.Windows.Data.IValueConverter, declare it in the resources in the same way and name it in the binding. The converters of TX Text Control show the pattern to follow: return DependencyProperty.UnsetValue for a value that can't be converted, and handle null, which InputFormat returns when the selected text has no common value.

Next Steps