How to: Bind Data to the MaskedTextBox Control

You can bind data to a MaskedTextBox control just as you can to any other Windows Forms control. However, if the format of your data in the database does not match the format expected by your mask definition, you will need to reformat the data. The following procedure demonstrates how to do this using the Format and Parse events of the Binding class to display separate phone number and phone extension database fields as a single editable field.

The following procedure requires that you have access to a SQL Server database with the Northwind sample database installed.

To bind data to a MaskedTextBox control

  1. Create a new Windows Forms project.

  2. Drag two TextBox controls onto your form; name them FirstName and LastName.

  3. Drag a MaskedTextBox control onto your form; name it PhoneMask.

  4. Set the Mask property of PhoneMask to (000) 000-0000 x9999.

  5. Add the following namespace imports to the form.

    using System.Data.SqlClient;
    
    Imports System.Data.SqlClient
    
  6. Right-click the form and choose View Code. Place this code anywhere in your form class.

    Binding currentBinding, phoneBinding;
    DataSet employeesTable = new DataSet();
    SqlConnection sc;
    SqlDataAdapter dataConnect;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        DoMaskBinding();
    }
    
    private void DoMaskBinding()
    {
        try
        {
            sc = new SqlConnection("Data Source=CLIENTUE;Initial Catalog=NORTHWIND;Integrated Security=SSPI");
            sc.Open();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return;
        }
    
        dataConnect = new SqlDataAdapter("SELECT * FROM Employees", sc);
        dataConnect.Fill(employeesTable, "Employees");
    
        // Now bind MaskedTextBox to appropriate field. Note that we must create the Binding objects
        // before adding them to the control - otherwise, we won't get a Format event on the 
        // initial load. 
        try
        {
            currentBinding = new Binding("Text", employeesTable, "Employees.FirstName");
            firstName.DataBindings.Add(currentBinding);
    
            currentBinding = new Binding("Text", employeesTable, "Employees.LastName");
            lastName.DataBindings.Add(currentBinding);
    
            phoneBinding =new Binding("Text", employeesTable, "Employees.HomePhone");
            // We must add the event handlers before we bind, or the Format event will not get called
            // for the first record.
            phoneBinding.Format += new ConvertEventHandler(phoneBinding_Format);
            phoneBinding.Parse += new ConvertEventHandler(phoneBinding_Parse);
            phoneMask.DataBindings.Add(phoneBinding);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return;
        }
    }
    
    Dim WithEvents CurrentBinding, PhoneBinding As Binding
    Dim EmployeesTable As New DataSet()
    Dim sc As SqlConnection
    Dim DataConnect As SqlDataAdapter
    
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        DoMaskedBinding()
    End Sub
    
    Private Sub DoMaskedBinding()
        Try
            sc = New SqlConnection("Data Source=SERVERNAME;Initial Catalog=NORTHWIND;Integrated Security=SSPI")
            sc.Open()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Exit Sub
        End Try
    
        DataConnect = New SqlDataAdapter("SELECT * FROM Employees", sc)
        DataConnect.Fill(EmployeesTable, "Employees")
    
        ' Now bind MaskedTextBox to appropriate field. Note that we must create the Binding objects
        ' before adding them to the control - otherwise, we won't get a Format event on the 
        ' initial load.
        Try
            CurrentBinding = New Binding("Text", EmployeesTable, "Employees.FirstName")
            firstName.DataBindings.Add(CurrentBinding)
            CurrentBinding = New Binding("Text", EmployeesTable, "Employees.LastName")
            lastName.DataBindings.Add(CurrentBinding)
            PhoneBinding = New Binding("Text", EmployeesTable, "Employees.HomePhone")
            PhoneMask.DataBindings.Add(PhoneBinding)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Application.Exit()
        End Try
    End Sub
    
  7. Add event handlers for the Format and Parse events to combine and separate the PhoneNumber and Extension fields from the bound DataSet.

    private void phoneBinding_Format(Object sender, ConvertEventArgs e)
    {
        String ext;
    
        DataRowView currentRow = (DataRowView)BindingContext[employeesTable, "Employees"].Current;
        if (currentRow["Extension"] == null) 
        {
            ext = "";
        } else 
        {
            ext = currentRow["Extension"].ToString();
        }
    
        e.Value = e.Value.ToString().Trim() + " x" + ext;
    }
    
    private void phoneBinding_Parse(Object sender, ConvertEventArgs e)
    {
        String phoneNumberAndExt = e.Value.ToString();
    
        int extIndex = phoneNumberAndExt.IndexOf("x");
        String ext = phoneNumberAndExt.Substring(extIndex).Trim();
        String phoneNumber = phoneNumberAndExt.Substring(0, extIndex).Trim();
    
        //Get the current binding object, and set the new extension manually. 
        DataRowView currentRow = (DataRowView)BindingContext[employeesTable, "Employees"].Current;
        // Remove the "x" from the extension.
        currentRow["Extension"] = ext.Substring(1);
    
        //Return the phone number.
        e.Value = phoneNumber;
    }
    
    Private Sub PhoneBinding_Format(ByVal sender As Object, ByVal e As ConvertEventArgs) Handles PhoneBinding.Format
        Dim Ext As String
    
        Dim CurrentRow As DataRowView = CType(Me.BindingContext(EmployeesTable, "Employees").Current, DataRowView)
        If (CurrentRow("Extension") Is Nothing) Then
            Ext = ""
        Else
            Ext = CurrentRow("Extension").ToString()
        End If
    
        e.Value = e.Value.ToString().Trim() & " x" & Ext
    End Sub
    
    Private Sub PhoneBinding_Parse(ByVal sender As Object, ByVal e As ConvertEventArgs) Handles PhoneBinding.Parse
        Dim PhoneNumberAndExt As String = e.Value.ToString()
    
        Dim ExtIndex As Integer = PhoneNumberAndExt.IndexOf("x")
        Dim Ext As String = PhoneNumberAndExt.Substring(ExtIndex).Trim()
        Dim PhoneNumber As String = PhoneNumberAndExt.Substring(0, ExtIndex).Trim()
    
        ' Get the current binding object, and set the new extension manually. 
        Dim CurrentRow As DataRowView = CType(Me.BindingContext(EmployeesTable, "Employees").Current, DataRowView)
        ' Remove the "x" from the extension.
        CurrentRow("Extension") = CObj(Ext.Substring(1))
    
        ' Return the phone number.
        e.Value = PhoneNumber
    End Sub
    
  8. Add two Button controls to the form. Name them previousButton and nextButton. Double-click each button to add a Click event handler, and fill in the event handlers as shown in the following code example.

    private void previousButton_Click(object sender, EventArgs e)
    {
        BindingContext[employeesTable, "Employees"].Position = BindingContext[employeesTable, "Employees"].Position - 1;
    }
    
    private void nextButton_Click(object sender, EventArgs e)
    {
        BindingContext[employeesTable, "Employees"].Position = BindingContext[employeesTable, "Employees"].Position + 1;
    }
    
    Private Sub PreviousButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PreviousButton.Click
        Me.BindingContext(EmployeesTable, "Employees").Position = Me.BindingContext(EmployeesTable, "Employees").Position - 1
    End Sub
    
    Private Sub NextButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NextButton.Click
        Me.BindingContext(EmployeesTable, "Employees").Position = Me.BindingContext(EmployeesTable, "Employees").Position + 1
    End Sub
    
  9. Run the sample. Edit the data, and use the Previous and Next buttons to see that the data is properly persisted to the DataSet.

Example

The following code example is the full code listing that results from completing the previous procedure.

Imports System.Data.SqlClient

Public Class Form1
    Dim WithEvents CurrentBinding, PhoneBinding As Binding
    Dim EmployeesTable As New DataSet()
    Dim sc As SqlConnection
    Dim DataConnect As SqlDataAdapter

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        DoMaskedBinding()
    End Sub

    Private Sub DoMaskedBinding()
        Try
            sc = New SqlConnection("Data Source=localhost;Initial Catalog=NORTHWIND;Integrated Security=SSPI")
            sc.Open()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Application.Exit()
        End Try

        DataConnect = New SqlDataAdapter("SELECT * FROM Employees", sc)
        DataConnect.Fill(EmployeesTable, "Employees")

        ' Now bind MaskedTextBox to appropriate field. Note that we must create the Binding objects
        ' before adding them to the control - otherwise, we won't get a Format event on the 
        ' initial load. 
        Try
            CurrentBinding = New Binding("Text", EmployeesTable, "Employees.FirstName")
            firstName.DataBindings.Add(CurrentBinding)
            CurrentBinding = New Binding("Text", EmployeesTable, "Employees.LastName")
            lastName.DataBindings.Add(CurrentBinding)
            PhoneBinding = New Binding("Text", EmployeesTable, "Employees.HomePhone")
            PhoneMask.DataBindings.Add(PhoneBinding)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Application.Exit()
        End Try
    End Sub

    Private Sub PhoneBinding_Format(ByVal sender As Object, ByVal e As ConvertEventArgs) Handles PhoneBinding.Format
        Dim Ext As String

        Dim CurrentRow As DataRowView = CType(Me.BindingContext(EmployeesTable, "Employees").Current, DataRowView)
        If (CurrentRow("Extension") Is Nothing) Then
            Ext = ""
        Else
            Ext = CurrentRow("Extension").ToString()
        End If

        e.Value = e.Value.ToString().Trim() & " x" & Ext
    End Sub

    Private Sub PhoneBinding_Parse(ByVal sender As Object, ByVal e As ConvertEventArgs) Handles PhoneBinding.Parse
        Dim PhoneNumberAndExt As String = e.Value.ToString()

        Dim ExtIndex As Integer = PhoneNumberAndExt.IndexOf("x")
        Dim Ext As String = PhoneNumberAndExt.Substring(ExtIndex).Trim()
        Dim PhoneNumber As String = PhoneNumberAndExt.Substring(0, ExtIndex).Trim()

        ' Get the current binding object, and set the new extension manually. 
        Dim CurrentRow As DataRowView = CType(Me.BindingContext(EmployeesTable, "Employees").Current, DataRowView)
        ' Remove the "x" from the extension.
        CurrentRow("Extension") = CObj(Ext.Substring(1))

        ' Return the phone number.
        e.Value = PhoneNumber
    End Sub

    Private Sub NextButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NextButton.Click
        Me.BindingContext(EmployeesTable, "Employees").Position = Me.BindingContext(EmployeesTable, "Employees").Position + 1
    End Sub

    Private Sub PreviousButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PreviousButton.Click
        Me.BindingContext(EmployeesTable, "Employees").Position = Me.BindingContext(EmployeesTable, "Employees").Position - 1
    End Sub
End Class
#region Using directives

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Data.SqlClient;

#endregion

namespace MaskedTextBoxDataCSharp
{
    partial class Form1 : Form
    {
        Binding currentBinding, phoneBinding;
        DataSet employeesTable = new DataSet();
        SqlConnection sc;
        SqlDataAdapter dataConnect;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DoMaskBinding();
        }

        private void DoMaskBinding()
        {
            try
            {
                sc = new SqlConnection("Data Source=localhost;Initial Catalog=NORTHWIND;Integrated Security=SSPI");
                sc.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            dataConnect = new SqlDataAdapter("SELECT * FROM Employees", sc);
            dataConnect.Fill(employeesTable, "Employees");

            
            // Now bind MaskedTextBox to appropriate field. Note that we must create the Binding objects
            // before adding them to the control - otherwise, we won't get a Format event on the 
            // initial load. 
            try
            {
                currentBinding = new Binding("Text", employeesTable, "Employees.FirstName");
                firstName.DataBindings.Add(currentBinding);
                
                currentBinding = new Binding("Text", employeesTable, "Employees.LastName");
                lastName.DataBindings.Add(currentBinding);

                phoneBinding =new Binding("Text", employeesTable, "Employees.HomePhone");
                // We must add the event handlers before we bind, or the Format event will not get called
                // for the first record.
                phoneBinding.Format += new ConvertEventHandler(phoneBinding_Format);
                phoneBinding.Parse += new ConvertEventHandler(phoneBinding_Parse);
                phoneMask.DataBindings.Add(phoneBinding);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }

        private void phoneBinding_Format(Object sender, ConvertEventArgs e)
        {
            String ext;

            DataRowView currentRow = (DataRowView)BindingContext[employeesTable, "Employees"].Current;
            if (currentRow["Extension"] == null) 
            {
                ext = "";
            } else 
            {
                ext = currentRow["Extension"].ToString();
            }

            e.Value = e.Value.ToString().Trim() + " x" + ext;
        }

        private void phoneBinding_Parse(Object sender, ConvertEventArgs e)
        {
            String phoneNumberAndExt = e.Value.ToString();

            int extIndex = phoneNumberAndExt.IndexOf("x");
            String ext = phoneNumberAndExt.Substring(extIndex).Trim();
            String phoneNumber = phoneNumberAndExt.Substring(0, extIndex).Trim();

            //Get the current binding object, and set the new extension manually. 
            DataRowView currentRow = (DataRowView)BindingContext[employeesTable, "Employees"].Current;
            // Remove the "x" from the extension.
            currentRow["Extension"] = ext.Substring(1);

            //Return the phone number.
            e.Value = phoneNumber;
        }

        private void previousButton_Click(object sender, EventArgs e)
        {
            BindingContext[employeesTable, "Employees"].Position = BindingContext[employeesTable, "Employees"].Position - 1;
        }

        private void nextButton_Click(object sender, EventArgs e)
        {
            BindingContext[employeesTable, "Employees"].Position = BindingContext[employeesTable, "Employees"].Position + 1;
        }
    }
}

Compiling the Code

  • Create a Visual C# or Visual Basic project.

  • Add the TextBox and MaskedTextBox controls to the form, as described in the previous procedure.

  • Open the source code file for the project's default form.

  • Replace the source code in this file with the code listed in the previous "Code" section.

  • Compile the application.

See Also

Tasks

Walkthrough: Working with the MaskedTextBox Control