Search code examples
c#datagridviewmaskedtextbox

C# How can i get a maskedtextbox column of a bound datagridview to not include the literals?


I have a datagridview which is bound to some data. One of the fields is a phone number and the phone number is stored in the database as an int (ex. 5555555555). I am using a masked textbox in another form just by itself with a phone number and its working perfectly. When it reads the value it applies the mask and also stores the changes as just the numbers.

I used the MaskedTextBox Column class that was from the Microsoft SDK however it is not working as intended. It is still trying to store the literals into the database. I'm going to list the code first for the column. Then I'll list the code I have for the classes on the MaskedTextBox Column.

        this.Phone.DataPropertyName = "Phone1";
        this.Phone.HeaderText = "Phone";
        this.Phone.HidePromptOnLeave = true;
        this.Phone.IncludeLiterals = false;
        this.Phone.IncludePrompt = false;
        this.Phone.Mask = "(999)000-0000";
        this.Phone.Name = "Phone";
        this.Phone.PromptChar = '\0';
        this.Phone.Resizable = System.Windows.Forms.DataGridViewTriState.True;
        this.Phone.SkipLiterals = true;
        this.Phone.SortMode  = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
        this.Phone.TextMaskFormat = System.Windows.Forms.MaskFormat.ExcludePromptAndLiterals;
        this.Phone.ValidatingType = typeof(int);

Then the MaskedTextBox Cell

using System;
using System.Windows.Forms;

namespace Microsoft.Samples.Windows.Forms.DataGridViewCustomColumn
{
class MaskedTextBoxCell : DataGridViewTextBoxCell
{
    private string mask;
    private char promptChar;
    private DataGridViewTriState includePrompt;
    private DataGridViewTriState includeLiterals;
    private DataGridViewTriState skipLiterals;
    private DataGridViewTriState hidePromptOnLeave;
    private Type validatingType;
    private MaskFormat textMaskFormat;

    //=------------------------------------------------------------------=
    // MaskedTextBoxCell
    //=------------------------------------------------------------------=
    /// <summary>
    ///   Initializes a new instance of this class.  Fortunately, there's
    ///   not much to do here except make sure that our base class is 
    ///   also initialized properly.
    /// </summary>
    /// 
    public MaskedTextBoxCell() : base()
    {
        this.mask = "";
        this.promptChar = '_';
        this.includePrompt = DataGridViewTriState.NotSet;
        this.includeLiterals = DataGridViewTriState.NotSet;
        this.hidePromptOnLeave = DataGridViewTriState.NotSet;
        this.skipLiterals = DataGridViewTriState.NotSet;
        this.validatingType = typeof(string);
        this.textMaskFormat = MaskFormat.ExcludePromptAndLiterals;

    }

    ///   Whenever the user is to begin editing a cell of this type, the editing
    ///   control must be created, which in this column type's
    ///   case is a subclass of the MaskedTextBox control.
    /// 
    ///   This routine sets up all the properties and values
    ///   on this control before the editing begins.
    public override void InitializeEditingControl(int rowIndex,
                                                  object initialFormattedValue,
                                                  DataGridViewCellStyle dataGridViewCellStyle)
    {
        MaskedTextBoxEditingControl mtbec;
        MaskedTextBoxColumn mtbcol;
        DataGridViewColumn dgvc;

        base.InitializeEditingControl(rowIndex, initialFormattedValue,
                                      dataGridViewCellStyle);

        mtbec = DataGridView.EditingControl as MaskedTextBoxEditingControl;

        //
        // set up props that are specific to the MaskedTextBox
        //

        dgvc = this.OwningColumn;   // this.DataGridView.Columns[this.ColumnIndex];
        if (dgvc is MaskedTextBoxColumn)
        {
            mtbcol = dgvc as MaskedTextBoxColumn;

            //
            // get the mask from this instance or the parent column.
            //
            if (string.IsNullOrEmpty(this.mask))
            {
                mtbec.Mask = mtbcol.Mask;
            }
            else
            {
                mtbec.Mask = this.mask;
            }

            //
            // prompt char.
            //
            mtbec.PromptChar = this.PromptChar;

            //
            // IncludePrompt
            //
            if (this.includePrompt == DataGridViewTriState.NotSet)
            {
                //mtbec.IncludePrompt = mtbcol.IncludePrompt;
            }
            else
            {
                //mtbec.IncludePrompt = BoolFromTri(this.includePrompt);
            }

            //
            // IncludeLiterals
            //
            if (this.includeLiterals == DataGridViewTriState.NotSet)
            {
                //mtbec.IncludeLiterals = mtbcol.IncludeLiterals;
            }
            else
            {
                //mtbec.IncludeLiterals = BoolFromTri(this.includeLiterals);
            }

            if (this.hidePromptOnLeave == DataGridViewTriState.NotSet)
            {
                //mtbec.HidePromptOnLeave = mtbcol.HidePromptOnLeave;
            }
            else
            {
                //mtbec.HidePromptOnLeave = BoolFromTri(this.hidePromptOnLeave);
            }

            if (this.skipLiterals == DataGridViewTriState.NotSet)
            {
                //mtbec.skipLiterals = mtbcol.SkipLiterals;
            }
            else
            {
                //mtbec.skipLiterals = BoolFromTri(this.SkipLiterals);
            }

            //
            // Finally, the validating type ...
            //
            if (this.ValidatingType == null)
            {
                mtbec.ValidatingType = mtbcol.ValidatingType;
            }
            else
            {
                mtbec.ValidatingType = this.ValidatingType;
            }

            //if (this.TextMaskFormat == null)
            //{
            //    mtbec.TextMaskFormat = mtbcol.TextMaskFormat;
            //}
            //else
            //{
            //    mtbec.TextMaskFormat = this.TextMaskFormat;
            //}

            mtbec.Text = (string)this.Value;
        }
    }

    //  Returns the type of the control that will be used for editing
    //  cells of this type.  This control must be a valid Windows Forms
    //  control and must implement IDataGridViewEditingControl.
    public override Type EditType
    {
        get
        {
            return typeof(MaskedTextBoxEditingControl);
        }
    }

    //   A string value containing the Mask against input for cells of
    //   this type will be verified.
    public virtual string Mask
    {
        get
        {
            return this.mask;
        }
        set
        {
            this.mask = value;
        }
    }

    //  The character to use for prompting for new input.
    // 
    public virtual char PromptChar
    {
        get
        {
            return this.promptChar;
        }
        set
        {
            this.promptChar = value;
        }
    }

    public virtual DataGridViewTriState SkipLiterals
    {
        get
        {
            return this.skipLiterals;
        }
        set
        {
            this.skipLiterals = value;
        }
    }


    //  A boolean indicating whether to include prompt characters in
    //  the Text property's value.
    public virtual DataGridViewTriState IncludePrompt
    {
        get
        {
            return this.includePrompt;
        }
        set
        {
            this.includePrompt = value;
        }
    }

    //  A boolean value indicating whether to include literal characters
    //  in the Text property's output value.
    public virtual DataGridViewTriState IncludeLiterals
    {
        get
        {
            return this.includeLiterals;
        }
        set
        {
            this.includeLiterals = value;
        }
    }

    //  A Type object for the validating type.
    public virtual Type ValidatingType
    {
        get
        {
            return this.validatingType;
        }
        set
        {
            this.validatingType = value;
        }
    }

    public virtual DataGridViewTriState HidePromptOnLeave
    {
        get
        {
            return this.hidePromptOnLeave;
        }
        set
        {
            this.hidePromptOnLeave = value;
        }
    }

    public virtual MaskFormat TextMaskFormat
    {
        get
        {
            return this.textMaskFormat;
        }
        set
        {
            this.textMaskFormat = value;
        }
    }



    //   Quick routine to convert from DataGridViewTriState to boolean.
    //   True goes to true while False and NotSet go to false.
    protected static bool BoolFromTri(DataGridViewTriState tri)
    {
        return (tri == DataGridViewTriState.True) ? true : false;
    }
}
}

Now the MaskedTextBox Column

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

namespace Microsoft.Samples.Windows.Forms.DataGridViewCustomColumn
{
//  The base object for the custom column type.  Programmers manipulate
//  the column types most often when working with the DataGridView, and
//  this one sets the basics and Cell Template values controlling the
//  default behaviour for cells of this column type.
public class MaskedTextBoxColumn : DataGridViewColumn
{
    private string mask;
    private char promptChar;
    private bool includePrompt;
    private bool includeLiterals;
    private Type validatingType;
    private bool skipLiterals;
    private bool hidePromptOnLeave;
    private MaskFormat textMaskFormat;

    //  Initializes a new instance of this class, making sure to pass
    //  to its base constructor an instance of a MaskedTextBoxCell 
    //  class to use as the basic template.
    public MaskedTextBoxColumn(): base(new MaskedTextBoxCell())
    {
    }

    //  Routine to convert from boolean to DataGridViewTriState.
    private static DataGridViewTriState TriBool(bool value)
    {
        return value ? DataGridViewTriState.True
                     : DataGridViewTriState.False;
    }


    //  The template cell that will be used for this column by default,
    //  unless a specific cell is set for a particular row.
    //
    //  A MaskedTextBoxCell cell which will serve as the template cell
    //  for this column.
    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }

        set
        {
            //  Only cell types that derive from MaskedTextBoxCell are supported as the cell template.
            if (value != null && !value.GetType().IsAssignableFrom(typeof(MaskedTextBoxCell)))
            {
                string s = "Cell type is not based upon the MaskedTextBoxCell.";//CustomColumnMain.GetResourceManager().GetString("excNotMaskedTextBox");
                throw new InvalidCastException(s);
            }

            base.CellTemplate = value;
        }
    }

    //  Indicates the Mask property that is used on the MaskedTextBox
    //  for entering new data into cells of this type.
    // 
    //  See the MaskedTextBox control documentation for more details.
    public virtual string Mask
    {
        get
        {
            return this.mask;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.mask != value)
            {
                this.mask = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.Mask = value;

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.Mask = value;
                        }
                    }
                }
            }
        }
    }


    //  By default, the MaskedTextBox uses the underscore (_) character
    //  to prompt for required characters.  This propertly lets you 
    //  choose a different one.
    // 
    //  See the MaskedTextBox control documentation for more details.
    public virtual char PromptChar
    {
        get
        {
            return this.promptChar;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.promptChar != value)
            {
                this.promptChar = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.PromptChar = value;

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.PromptChar = value;
                        }
                    }
                }
            }
        }
    }

    //   Indicates whether any unfilled characters in the mask should be
    //   be included as prompt characters when somebody asks for the text
    //   of the MaskedTextBox for a particular cell programmatically.
    // 
    //   See the MaskedTextBox control documentation for more details.
    public virtual bool IncludePrompt
    {
        get
        {
            return this.includePrompt;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.includePrompt != value)
            {
                this.includePrompt = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.IncludePrompt = TriBool(value);

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.IncludePrompt = TriBool(value);
                        }
                    }
                }
            }
        }
    }

    public virtual bool HidePromptOnLeave
    {
        get
        {
            return this.hidePromptOnLeave;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.hidePromptOnLeave != value)
            {
                this.hidePromptOnLeave = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.SkipLiterals = TriBool(value);

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.SkipLiterals = TriBool(value);
                        }
                    }
                }
            }
        }
    }

    public virtual bool SkipLiterals
    {
        get
        {
            return this.skipLiterals;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.skipLiterals != value)
            {
                this.skipLiterals = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.HidePromptOnLeave = TriBool(value);

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.HidePromptOnLeave = TriBool(value);
                        }
                    }
                }
            }
        }
    }

    //  Controls whether or not literal (non-prompt) characters should
    //  be included in the output of the Text property for newly entered
    //  data in a cell of this type.
    // 
    //  See the MaskedTextBox control documentation for more details.
    public virtual bool IncludeLiterals
    {
        get
        {
            return this.includeLiterals;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.includeLiterals != value)
            {
                this.includeLiterals = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.IncludeLiterals = TriBool(value);

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {

                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.IncludeLiterals = TriBool(value);
                        }
                    }
                }
            }
        }
    }

    //  Indicates the type against any data entered in the MaskedTextBox
    //  should be validated.  The MaskedTextBox control will attempt to
    //  instantiate this type and assign the value from the contents of
    //  the text box.  An error will occur if it fails to assign to this
    //  type.
    //
    //  See the MaskedTextBox control documentation for more details.
    public virtual Type ValidatingType
    {
        get
        {
            return this.validatingType;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.validatingType != value)
            {
                this.validatingType = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.ValidatingType = value;

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.ValidatingType = value;
                        }
                    }
                }
            }
        }
    }

    public virtual MaskFormat TextMaskFormat
    {
        get
        {
            return this.textMaskFormat;
        }
        set
        {
            MaskedTextBoxCell mtbc;
            DataGridViewCell dgvc;
            int rowCount;

            if (this.textMaskFormat != value)
            {
                this.textMaskFormat = value;

                //
                // first, update the value on the template cell.
                //
                mtbc = (MaskedTextBoxCell)this.CellTemplate;
                mtbc.TextMaskFormat = value;

                //
                // now set it on all cells in other rows as well.
                //
                if (this.DataGridView != null && this.DataGridView.Rows != null)
                {
                    rowCount = this.DataGridView.Rows.Count;
                    for (int x = 0; x < rowCount; x++)
                    {
                        dgvc = this.DataGridView.Rows.SharedRow(x).Cells[x];
                        if (dgvc is MaskedTextBoxCell)
                        {
                            mtbc = (MaskedTextBoxCell)dgvc;
                            mtbc.TextMaskFormat = value;
                        }
                    }
                }
            }
        }
    }

}
}

Solution

  • I ended up working around this by making my database writes remove the extra characters before it stored it. It only shows the parentheses and dashes when you click into the box but that is acceptable for my needs as long as the mask is there when the user is entering the data.