# Data Binding and Database Storage

> Bind Windows Forms controls to InputFormat with DataBindings, bind a TextControl to a BindingSource record and store documents as byte arrays in a database.

- **Product:** TX Text Control .NET for Windows Forms
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for Windows Forms > Integration Guide > Data Binding and Database Storage
- **5899 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/data-binding/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/data-binding/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/data-binding/llms-full.txt

---

Windows Forms data binding connects a property of one object to a property of another, so that a value shown in a control follows the data without event handlers. With a `TextControl`, it serves two purposes: controls such as check boxes and combo boxes follow the formatting at the input position, and the document itself comes from and goes back to a record of a table. The sections below cover both and end with reading and writing documents in a database.

Filling a template with the values of a database, rather than editing a stored document, is mail merge: see [Mail Merge](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/llms-full.txt) and [DataSets and DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/data-sources/datasets/llms-full.txt).

### What Can Be Bound

| Binding | Source | Page section |
|---|---|---|
| Formatting at the input position, such as bold text or the font | [InputFormat](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputformat/llms-full.txt), returned by [TextControl.InputFormat](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/inputformat-property/llms-full.txt) | [Bind Controls to the Formatting](#bind-controls-to-the-formatting) |
| The document of the current record | A property of your own that calls [Load](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/load-method/llms-full.txt) and [Save](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/save-method/llms-full.txt) | [Bind the Document to a Record](#bind-the-document-to-a-record) |
| A document column of a table, loaded and saved when the record changes | The `CurrentChanged` event of a `BindingSource` | [Load and Save When the Record Changes](#load-and-save-when-the-record-changes) |

`TextControl` has no documented property that holds the formatted document, the way the `Rtf` property of a `RichTextBox` does. The content therefore reaches a data source through `Load` and `Save`, either inside a bindable property or in an event handler.

### Bind Controls to the Formatting

`InputFormat` represents the formatting attributes at the current input position. Its properties are updated when the input position moves, which makes the object a data source for the `DataBindings` of other controls. If text is selected and the selection has no common value for an attribute, the property is `null`.

The following *Form1.cs* belongs to a form with a `TextControl` named `textControl1`, a `CheckBox` named `checkBoxBold` and two `ComboBox` controls named `comboBoxFont` and `comboBoxSize`, all added in the designer:

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

namespace MyWinFormsApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // A check box that shows and sets bold text
            checkBoxBold.DataBindings.Add("Checked", textControl1.InputFormat, "Bold",
                true, DataSourceUpdateMode.OnPropertyChanged);

            // A combo box with the fonts of the editor
            comboBoxFont.DataSource = textControl1.GetSupportedFonts();
            comboBoxFont.DataBindings.Add("Text", textControl1.InputFormat, "FontFamily",
                true, DataSourceUpdateMode.OnPropertyChanged);

            // A combo box for the font size: InputFormat uses twips, the box shows points
            Binding sizeBinding = new Binding("Text", textControl1.InputFormat, "FontSize",
                true, DataSourceUpdateMode.OnPropertyChanged);
            sizeBinding.Format += SizeBinding_Format;
            sizeBinding.Parse += SizeBinding_Parse;
            comboBoxSize.DataBindings.Add(sizeBinding);
        }

        private void SizeBinding_Format(object sender, ConvertEventArgs e)
        {
            // Twips to points for the display
            if (e.Value is int twips)
            {
                e.Value = (twips / 20).ToString();
            }
        }

        private void SizeBinding_Parse(object sender, ConvertEventArgs e)
        {
            // Points to twips for the editor
            if (int.TryParse(e.Value as string, out int points))
            {
                e.Value = points * 20;
            }
        }
    }
}
```

Keep the namespace Visual Studio created for your project. Set the `Appearance` of the check box to `Button` in the designer if it should look like a toolbar button.

The code works as follows:

- `DataBindings.Add` connects a property of the control, such as `Checked`, to a property of the data source, here [InputFormat.Bold](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputformat/bold-property/llms-full.txt). `DataSourceUpdateMode.OnPropertyChanged` writes a change of the check box to the editor at once, so that clicking it makes the selected text bold.
- [GetSupportedFonts](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/getsupportedfonts-method/llms-full.txt) returns the names of the fonts the editor can use. It returns `null` before the control is completely initialized, which is why the bindings are set up in the `Load` event of the form. The `Text` of the combo box follows [InputFormat.FontFamily](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputformat/fontfamily-property/llms-full.txt).
- [InputFormat.FontSize](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputformat/fontsize-property/llms-full.txt) is in twips, a twentieth of a point. Windows Forms has no value converters for this, so the `Format` event of the `Binding` converts twips to points for the combo box and the `Parse` event converts the typed value back.

The same pattern works for every property of `InputFormat`, from `Italic` and `Underline` to the paragraph alignment and the list format.

### Bind the Document to a Record

A property that loads and saves the document makes the content bindable like any other property. The following class derives from `TextControl` and adds an `Rtf` property, which reads and writes the document as an RTF string. Add it as *RtfTextControl.cs* to the project:

```csharp
using System.ComponentModel;
using TXTextControl;

namespace MyWinFormsApp
{
    public class RtfTextControl : TXTextControl.TextControl
    {
        public RtfTextControl()
        {
            // Create the control now, so that Load and Save work before the form is shown
            CreateControl();
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string Rtf
        {
            get
            {
                string data;
                Save(out data, StringStreamType.RichTextFormat);
                return data;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    ResetContents();
                }
                else
                {
                    Load(value, StringStreamType.RichTextFormat);
                }
            }
        }
    }
}
```

Build the project, and `RtfTextControl` appears in the toolbox. Add it to a form with a `BindingSource` named `bindingSource1` and a `BindingNavigator` named `bindingNavigator1`, and bind it in the `Load` event of the form:

```csharp
private void Form1_Load(object sender, EventArgs e)
{
    // Three records with an RTF column
    DataTable table = new DataTable("Letters");
    table.Columns.Add("Body", typeof(string));
    table.Rows.Add(@"{\rtf1 First letter\par}");
    table.Rows.Add(@"{\rtf1 Second letter\par}");
    table.Rows.Add(@"{\rtf1 Third letter\par}");

    bindingSource1.DataSource = table;
    bindingNavigator1.BindingSource = bindingSource1;

    // Bind the Rtf property to the Body column
    rtfTextControl1.DataBindings.Add("Rtf", bindingSource1, "Body");
}
```

It needs `using System.Data;` for `DataTable`. Run the application and click the arrows of the navigator: the editor shows the letter of each record.

![A Windows Forms form with a BindingNavigator at record 2 of 3 above a TextControl with its button bar, rulers and status bar, showing the text of the second record.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-winforms/binding-navigator-form.5a5fdad3.webp)

The code works as follows:

- The getter of `Rtf` calls [Save](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/save-method/llms-full.txt) with [StringStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/stringstreamtype/enumeration/llms-full.txt) `RichTextFormat`; the setter calls [Load](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/load-method/llms-full.txt), or [ResetContents](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/resetcontents-method/llms-full.txt) for an empty value. `HTMLFormat` works the same way for an HTML column.
- The two attributes keep the property out of the **Properties** window and out of the code the designer writes.
- Windows Forms reads the getter when it writes the value back to the record, by default when the control is validated, for example when the user moves the focus to another control. The edits of a letter are then in its row of the table.

Text Control publishes this approach as the sample [TextControl.WindowsForms.PropertyBinding](https://github.com/TextControl/TextControl.WindowsForms.PropertyBinding), described in the blog article [RichTextBox Compatible Data Binding with TX Text Control](https://www.textcontrol.com/blog/2015/01/05/richtextbox-compatible-data-binding-with-tx-text-control/).

### Load and Save When the Record Changes

Instead of a derived control, an event handler can move the document between the editor and the table. The `CurrentChanged` event of a `BindingSource` occurs when the user moves to another record: the handler first stores the document of the record that is left and then loads the one of the new record. The following form keeps the documents in a byte array column, in the TX Text Control format:

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

namespace MyWinFormsApp
{
    public partial class Form1 : Form
    {
        private readonly DataTable documents = new DataTable("Documents");
        private DataRowView currentRow;

        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
            FormClosing += Form1_FormClosing;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Id, name and content of each document
            documents.Columns.Add("Id", typeof(int));
            documents.Columns.Add("Name", typeof(string));
            documents.Columns.Add("Content", typeof(byte[]));

            // Fill the table from your database here
            documents.Rows.Add(1, "Offer", null);
            documents.Rows.Add(2, "Contract", null);

            bindingSource1.DataSource = documents;
            bindingSource1.CurrentChanged += BindingSource1_CurrentChanged;
            BindingSource1_CurrentChanged(bindingSource1, EventArgs.Empty);
        }

        private void BindingSource1_CurrentChanged(object sender, EventArgs e)
        {
            // Keep the edits of the document the user leaves
            StoreCurrentDocument();

            currentRow = bindingSource1.Current as DataRowView;
            if (currentRow == null)
            {
                return;
            }

            // Show the document of the new record
            if (currentRow["Content"] is byte[] content)
            {
                textControl1.Load(content, BinaryStreamType.InternalUnicodeFormat);
            }
            else
            {
                textControl1.ResetContents();
            }
        }

        private void StoreCurrentDocument()
        {
            if (currentRow == null)
            {
                return;
            }

            byte[] content;
            textControl1.Save(out content, BinaryStreamType.InternalUnicodeFormat);
            currentRow["Content"] = content;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            StoreCurrentDocument();
            // Write the changed rows of documents to your database here
        }
    }
}
```

The form has a `TextControl` named `textControl1` and a `BindingSource` named `bindingSource1`; a `BindingNavigator` or a `ListBox` bound to `bindingSource1` lets the user choose the record.

The code works as follows:

- [BinaryStreamType](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/binarystreamtype/enumeration/llms-full.txt) `InternalUnicodeFormat` is the TX Text Control format. It keeps everything the editor supports, so a document looks the same the next time it is loaded. [Store Documents in a Database](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/load-save/#store-documents-in-a-database) explains why Text Control recommends it for documents that are still edited.
- `StoreCurrentDocument` runs before a new record is loaded and when the form closes, so that no edit is lost.
- A new record with an empty `Content` column gets an empty document.

A Microsoft SQL Server sample of Text Control, described in [Using TX Text Control As a Bound Control with MS SQL Server](https://www.textcontrol.com/blog/2010/06/24/using-tx-text-control-as-a-bound-control-with-ms-sql-server/), uses the same event with a `TableAdapter` created by the Visual Studio data wizards and stores RTF strings.

### Read and Write Documents in a Database

A document column holds binary data: `varbinary(max)` in SQL Server, for example, or `BLOB` in other databases. Pass the byte array as a parameter of the command; the classes of `System.Data.Common` work with the provider of any database:

```csharp
using System.Data;
using System.Data.Common;

namespace MyWinFormsApp
{
    public static class DocumentStore
    {
        public static void SaveDocument(DbConnection connection, int id, byte[] content)
        {
            using DbCommand command = connection.CreateCommand();
            command.CommandText = "UPDATE Documents SET Content = @content WHERE Id = @id";

            DbParameter contentParameter = command.CreateParameter();
            contentParameter.ParameterName = "@content";
            contentParameter.DbType = DbType.Binary;
            contentParameter.Value = content;
            command.Parameters.Add(contentParameter);

            DbParameter idParameter = command.CreateParameter();
            idParameter.ParameterName = "@id";
            idParameter.Value = id;
            command.Parameters.Add(idParameter);

            command.ExecuteNonQuery();
        }

        public static byte[] LoadDocument(DbConnection connection, int id)
        {
            using DbCommand command = connection.CreateCommand();
            command.CommandText = "SELECT Content FROM Documents WHERE Id = @id";

            DbParameter idParameter = command.CreateParameter();
            idParameter.ParameterName = "@id";
            idParameter.Value = id;
            command.Parameters.Add(idParameter);

            return command.ExecuteScalar() as byte[];
        }
    }
}
```

Open the connection with the provider of your database, such as `SqlConnection` of the package *Microsoft.Data.SqlClient*, and pass it in. The `@` prefix of the parameter names is the one SQL Server and SQLite use; other providers may expect another. The editor side stays the same: `Save(out content, BinaryStreamType.InternalUnicodeFormat)` before `SaveDocument`, and `Load(content, BinaryStreamType.InternalUnicodeFormat)` after `LoadDocument`.

To store documents for display or exchange rather than for further editing, save them as DOCX or PDF with `BinaryStreamType.WordprocessingML` or `AdobePDF` instead; these formats require the Professional or Enterprise edition, see [Editions and Feature Availability](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/overview/editions/llms-full.txt).

### Next Steps

- [Loading and Saving Documents](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/load-save/llms-full.txt): every format, and the settings of `Load` and `Save`.
- [Events](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/events/llms-full.txt): track unsaved changes with the `Changed` event.
- [Integrating Existing Menus and Toolbars](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/menus-toolbars/llms-full.txt): connect the menus and toolbars of your form to the editor.
- [DataSets and DataTables](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/mail-merge/data-sources/datasets/llms-full.txt): merge database tables into templates.

---

## Nearby

- **Previous:** [Embedding the Editor in Forms and UserControls](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/embedding/llms-full.txt)
- **Next:** [Integrating Existing Menus and Toolbars](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/integration/menus-toolbars/llms-full.txt)
