# Binding Document Content

> Bind WPF toolbars to InputFormat and CanUndo in XAML, and bind the whole document to a view model byte array with an attached property using Load and Save.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Integration Guide > Data Binding > Binding Document Content
- **6207 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/document-content/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/document-content/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/document-content/llms-full.txt

---

What in a document can a WPF binding reach? Two things: the formatting at the input position, which TX Text Control exposes for bindings, and the document as a whole, which needs a small class of your own because the `TextControl` has no dependency property for it. Both are shown below, the first in XAML only, the second with an attached property that connects the editor to a `byte[]` property of a view model.

### What Can Be Bound

| Content | Binding | Direction |
|---|---|---|
| Formatting at the input position: font, size, bold, alignment, lists, style | `ElementName=textControl1, Path=InputFormat.<property>` | Both ways |
| State of the editor, such as whether undo is possible | `ElementName=textControl1, Path=CanUndo` | From the editor |
| The whole document | An attached property that calls `Load` and `Save` | Both ways |

The target of a WPF binding must be a dependency property. The [InputFormat](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/llms-full.txt) properties and `CanUndo` are sources, so the targets are the properties of your controls, such as `IsChecked` or `Text`. [TextControl.Text](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/text-property/llms-full.txt) gets or sets the text contents as a string, but it isn't a dependency property and can't be the target of a binding; the formatted document is read and written with [Load](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/load-method/llms-full.txt) and [Save](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/save-method/llms-full.txt).

### Bind to the Formatting at the Input Position

[TextControl.InputFormat](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/inputformat-property/llms-full.txt) returns an `InputFormat` object that represents all formatting attributes at the current input position. Its properties are updated automatically when the input position changes, and setting one of them formats the selected text. If the selection has no common value for an attribute, the property is `null`.

The following *MainWindow.xaml* puts a style list, a font list, bold and italic buttons and undo and redo buttons above the editor:

```xml
<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">
    <DockPanel>
        <ToolBar DockPanel.Dock="Top">
            <ComboBox x:Name="styleComboBox" Width="140" IsEditable="True" IsReadOnly="True"
                      Text="{Binding ElementName=textControl1, Path=InputFormat.StyleName}"
                      ItemsSource="{Binding ElementName=textControl1, Path=InputFormat.StyleNames}" />
            <ComboBox x:Name="fontComboBox" Width="160" IsEditable="True" IsReadOnly="True"
                      DropDownOpened="FontComboBox_DropDownOpened"
                      Text="{Binding ElementName=textControl1, Path=InputFormat.FontFamily}" />
            <ToggleButton Content="B" Focusable="False"
                          IsChecked="{Binding ElementName=textControl1, Path=InputFormat.Bold, Mode=TwoWay}" />
            <ToggleButton Content="I" Focusable="False"
                          IsChecked="{Binding ElementName=textControl1, Path=InputFormat.Italic, Mode=TwoWay}" />
            <Separator />
            <Button Content="Undo" Focusable="False" Click="UndoButton_Click"
                    IsEnabled="{Binding ElementName=textControl1, Path=CanUndo}" />
            <Button Content="Redo" Focusable="False" Click="RedoButton_Click"
                    IsEnabled="{Binding ElementName=textControl1, Path=CanRedo}" />
        </ToolBar>
        <WPF:TextControl x:Name="textControl1" />
    </DockPanel>
</Window>
```

Three short handlers go into *MainWindow.xaml.cs*:

```csharp
using System;
using System.Windows;

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

        private void FontComboBox_DropDownOpened(object sender, EventArgs e)
        {
            // Fill the list with the fonts the editor supports
            fontComboBox.ItemsSource = textControl1.InputFormat.GetFontFamilies();
        }

        private void UndoButton_Click(object sender, RoutedEventArgs e)
        {
            textControl1.Undo();
        }

        private void RedoButton_Click(object sender, RoutedEventArgs e)
        {
            textControl1.Redo();
        }
    }
}
```

The XAML works as follows:

- `ElementName=textControl1` makes the `TextControl` the source, and `Path` names the property: [StyleName](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/stylename-property/llms-full.txt) and [StyleNames](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/stylenames-property/llms-full.txt) for the formatting styles of the document, [FontFamily](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/fontfamily-property/llms-full.txt) for the font, [Bold](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/bold-property/llms-full.txt) and [Italic](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/italic-property/llms-full.txt) for the buttons.
- `Mode=TwoWay` on the toggle buttons sends a click back to the editor, so that the selected text becomes bold or italic.
- `Focusable="False"` keeps the keyboard focus, and with it the selection, in the editor when a button is clicked.
- [GetFontFamilies](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/getfontfamilies-method/llms-full.txt) returns the fonts the editor can use. The handler fills the list when it opens, as in the example of the reference.
- [CanUndo](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/canundo-property/llms-full.txt) and [CanRedo](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/canredo-property/llms-full.txt) enable the buttons, as the quick access toolbar of the TX Words ribbon sample does. [Undo](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/undo-method/llms-full.txt) and [Redo](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/redo-method/llms-full.txt) do the work in the `Click` handlers; [Commands and Input Bindings](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/commands/llms-full.txt) replaces the handlers with commands.

Run the application and move the caret through text with different formatting: the lists and buttons follow it. Properties in twips, such as [FontSize](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/fontsize-property/llms-full.txt), or of the type `System.Drawing.Color`, such as [TextColor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputformat/textcolor-property/llms-full.txt), need a converter before a WPF control can show them; see [Value Converters](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/value-converters/llms-full.txt).

### Bind the Whole Document

A view model that keeps a document, for example a letter loaded from a database, holds it as data, not as a control. An attached property can connect such data to the editor: WPF calls it when the bound value changes, and it loads the value into the `TextControl`; when the user edits the document, it saves the document and writes it back to the binding. Add the class as *DocumentContent.cs* to the project:

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

namespace MyWPFApp
{
    public static class DocumentContent
    {
        // The document as a byte array in the TX Text Control format
        public static readonly DependencyProperty DataProperty =
            DependencyProperty.RegisterAttached(
                "Data",
                typeof(byte[]),
                typeof(DocumentContent),
                new FrameworkPropertyMetadata(
                    null,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnDataChanged));

        // True while the editor and the property are being synchronized
        private static readonly DependencyProperty IsUpdatingProperty =
            DependencyProperty.RegisterAttached(
                "IsUpdating", typeof(bool), typeof(DocumentContent), new PropertyMetadata(false));

        // True once the Changed handler is connected
        private static readonly DependencyProperty IsConnectedProperty =
            DependencyProperty.RegisterAttached(
                "IsConnected", typeof(bool), typeof(DocumentContent), new PropertyMetadata(false));

        public static byte[] GetData(DependencyObject element)
        {
            return (byte[])element.GetValue(DataProperty);
        }

        public static void SetData(DependencyObject element, byte[] value)
        {
            element.SetValue(DataProperty, value);
        }

        private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not TXTextControl.WPF.TextControl textControl)
            {
                return;
            }

            if (!(bool)textControl.GetValue(IsConnectedProperty))
            {
                textControl.Changed += TextControl_Changed;
                textControl.SetValue(IsConnectedProperty, true);
            }

            // The new value came from the editor itself
            if ((bool)textControl.GetValue(IsUpdatingProperty))
            {
                return;
            }

            if (textControl.IsLoaded)
            {
                LoadDocument(textControl, (byte[])e.NewValue);
            }
            else
            {
                // Load the document as soon as the control is ready
                textControl.Loaded -= TextControl_Loaded;
                textControl.Loaded += TextControl_Loaded;
            }
        }

        private static void TextControl_Loaded(object sender, RoutedEventArgs e)
        {
            TXTextControl.WPF.TextControl textControl = (TXTextControl.WPF.TextControl)sender;
            textControl.Loaded -= TextControl_Loaded;
            LoadDocument(textControl, GetData(textControl));
        }

        private static void LoadDocument(TXTextControl.WPF.TextControl textControl, byte[] data)
        {
            textControl.SetValue(IsUpdatingProperty, true);
            try
            {
                if (data == null)
                {
                    textControl.ResetContents();
                }
                else
                {
                    textControl.Load(data, BinaryStreamType.InternalUnicodeFormat);
                }
            }
            finally
            {
                textControl.SetValue(IsUpdatingProperty, false);
            }
        }

        private static void TextControl_Changed(object sender, EventArgs e)
        {
            TXTextControl.WPF.TextControl textControl = (TXTextControl.WPF.TextControl)sender;
            if ((bool)textControl.GetValue(IsUpdatingProperty))
            {
                return;
            }

            // Write the edited document back to the bound property
            byte[] data;
            textControl.Save(out data, BinaryStreamType.InternalUnicodeFormat);

            textControl.SetValue(IsUpdatingProperty, true);
            try
            {
                textControl.SetCurrentValue(DataProperty, data);
            }
            finally
            {
                textControl.SetValue(IsUpdatingProperty, false);
            }
        }
    }
}
```

The view model, *LetterViewModel.cs*, has the property the editor binds to and a second one that shows the size of the stored document:

```csharp
using System.ComponentModel;

namespace MyWPFApp
{
    public class LetterViewModel : INotifyPropertyChanged
    {
        private byte[] body;

        public event PropertyChangedEventHandler PropertyChanged;

        // The letter in the TX Text Control format, as stored in the database
        public byte[] Body
        {
            get { return body; }
            set
            {
                body = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Body)));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Size)));
            }
        }

        public int Size
        {
            get { return body == null ? 0 : body.Length; }
        }
    }
}
```

In *MainWindow.xaml*, the attached property binds the editor to `Body`. The prefix `local` maps the namespace of the project:

```xml
<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"
        xmlns:local="clr-namespace:MyWPFApp"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel>
        <TextBlock DockPanel.Dock="Bottom" Margin="4"
                   Text="{Binding Size, StringFormat=Stored document: {0} bytes}" />
        <WPF:TextControl x:Name="textControl1"
                         local:DocumentContent.Data="{Binding Body}" />
    </DockPanel>
</Window>
```

The constructor in *MainWindow.xaml.cs* sets the view model as the data context:

```csharp
public MainWindow()
{
    InitializeComponent();
    DataContext = new LetterViewModel();
}
```

Run the application and type: the size below the editor changes with every edit, because each change is saved into `Body`. Assign a byte array to `Body`, and the editor shows that document.

The code works as follows:

- `RegisterAttached` creates a dependency property that any element can carry, here the `TextControl`. `BindsTwoWayByDefault` makes `{Binding Body}` work in both directions without `Mode=TwoWay`.
- `OnDataChanged` runs when the bound value changes. Before the control has been loaded into the window, the editor isn't ready for a document yet (see [Control Initialization](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/troubleshooting/initialization/llms-full.txt)), so the load waits for the `Loaded` event.
- [Changed](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/changed-event/llms-full.txt) occurs when the contents of the document have changed. The handler saves the document and hands it to the binding with `SetCurrentValue`, which keeps the binding in place.
- `IsUpdating` marks the moments in which the class itself loads or writes a value, so that a change doesn't travel back to where it came from.
- [BinaryStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/binarystreamtype/enumeration/llms-full.txt) `InternalUnicodeFormat` is the TX Text Control format, which keeps everything the editor supports. An empty value, `null`, clears the editor with [ResetContents](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/resetcontents-method/llms-full.txt).

Saving on every change keeps the view model current at all times, and it saves the whole document each time. For long documents, save less often: let the view model ask for the document when it needs it, for example in its **Save** command, as [MVVM Integration Patterns](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/mvvm/llms-full.txt) shows.

### Choose the Format of the Bound Data

The attached property stores the TX Text Control format, the right choice for documents that users go on editing. Other formats need only two lines changed:

| Stored as | `Load` and `Save` with | Property type |
|---|---|---|
| TX Text Control format | `BinaryStreamType.InternalUnicodeFormat` | `byte[]` |
| DOCX | `BinaryStreamType.WordprocessingML` | `byte[]` |
| RTF | [StringStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/stringstreamtype/enumeration/llms-full.txt) `RichTextFormat` | `string` |
| HTML | `StringStreamType.HTMLFormat` | `string` |

For a string format, register the property with `typeof(string)` and use the `Load(string, StringStreamType)` and `Save(out string, StringStreamType)` overloads. DOCX requires the Professional or Enterprise edition; see [Editions and Feature Availability](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/overview/editions/llms-full.txt). What each format keeps is listed in [Supported File Formats](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/overview/file-formats/llms-full.txt).

### Next Steps

- [Value Converters](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/value-converters/llms-full.txt): twips, colors, list formats and zoom factors in bindings.
- [MVVM Integration Patterns](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/mvvm/llms-full.txt): the editor in a view with a view model and commands.
- [Load and Save Documents](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/document-editor/load-save/llms-full.txt): **Open** and **Save** with the built-in dialog boxes.
- [TextControlDocument](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/textcontroldocument/llms-full.txt): the element of the template that shows the document.

---

## Nearby

- **Previous:** [TextControlDocument](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/textcontroldocument/llms-full.txt)
- **Next:** [Value Converters](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/integration/data-binding/value-converters/llms-full.txt)
