Value Converters
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.
| Converter | From the editor | To the WPF control | Typical use |
|---|---|---|---|
| MeasureConverter | int in twips | string or double in another unit | Font sizes, indents, paragraph distances |
| ColorConverter | System.Drawing.Color | System.Windows.Media.Color | Text and background colors |
| BooleanConverter | An enumeration value, int, char or bool? | bool | Radio buttons, check marks in menus, toggle buttons |
| LogarithmicConverter | A number on a linear scale | A number on a logarithmic scale | A 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:
Unit | The converted value is in |
|---|---|
Point | Points, 1/72 inch |
Centimeter | Centimeters |
Millimeter | Millimeters |
CentiInch | 1/100 inch |
StandardWPF | 1/96 inch, the device-independent units of WPF |
Twips | Twips, 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:
- InputMinimum and InputMaximum, 10 and 400, are the range of the source, here ZoomFactor in percent. Smaller or larger values are treated as the bounds.
- InputCenter, 100, is the source value that lands in the middle of the slider.
- OutputMinimum and OutputMaximum, 0 and 100, match the
MinimumandMaximumof the slider.
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
- Binding Document Content: the bindings to
InputFormatand to the whole document. - Resource Dictionaries and Styling: converters and styles for the whole application.
- Data Binding: how bindings to the
TextControlwork.