DataGridView Password Column

Windows Forms have a few column types for DataGridView including DataGridViewTextBoxColumn, DataGridViewCheckBoxColumn, DataGridViewComboBoxColumn, DataGridViewImageColumn, DataGridViewButtonColumn and DataGridViewLinkColumn. You can also create custom columns for DataGridView by deriving from DataGridViewColumn or any of mentioned classes and provide a new appearance and behavior for your custom column.

In this post I’m going to show how to create a column type to show and edit passwords, called DataGridViewPasswordColumn.

DataGridViewPasswordColumn

Creating Custom Column in DataGridView – Basic Rules

There are 3 main pillars for a new column type:

  • DataGridViewColumn is responsible for properties which you set in design mode in column editor of the control.
  • DataGridViewCell is responsible for rendering the value and initialize the editing control.
  • DataGridViewEditingControl is responsible for editing the value of the cell.

When creating a new column you can derive from DataGridViewColumn or one of its derived classes. Also when creating a new cell for the column, you can derive from DataGridViewCell or one of its derived classes. Also when creating a new editing control, you can derive from one of the existing editing controls, or you can start by deriving from a control class and implementing IDataGridViewEditingControl interface.

When creating a custom cell, here are the guidelines that you should follow:

  1. Your custom cell should have the same properties which the custom column has. Also the editing control should have the same properties.
  2. In your custom column, in getter of properties, you should get the property value from CellTemplate.
  3. In your custom column, in setter of properties, set the property value to CellTemplate. Also, im most cases, you neecd to set the property value for all cells of the column using a for loop, because the user expect column settings apply to all cells.
  4. In your custom cell, you need to override Clone and make sure you perform a deep copy of properties of custom cell. But since you store property values in cell template, you don’t need to override Clone for custom column. Cloning is important for designer.
  5. In your custom cell, in InitializeEditingControl you should setup editing control using properties of the custom cell. Also, in most cases, you need to keep a reference to the editing control, and update properties of the editing control in setter of properties of the cell, because the user expect to see changes on the editing control if a property of column changed.
  6. In your custom editing control, you need to handle the event which is raised by changing value (here in your case OnTextChanged) and then notify the DataGridView that the cell has been dirty using this.EditingControlDataGridView.NotifyCurrentCellDirty(true);

You can see the rules which I mentioned in source codes related to ComboBox column:

Creating DataGridView Password Column

To create a a password column called DataGridViewPasswordColumn, for the column we can derive from DataGridViewTextBoxColumn. For the cell we can derive from DataGridViewTextBoxCell and for the editing control we don’t need to do anything other than configuring the default editing control of the DataGridViewTextBoxCell.

We need a property called UsePasswordCharWhenEditing which tells us if we should use the password character when editing the field.

Here is the code for the the column and the cell:

using System.Drawing;
using System.Windows.Forms;
public class DataGridViewPasswordColumn : DataGridViewTextBoxColumn
{
    public DataGridViewPasswordColumn()
    {
        this.CellTemplate = new DataGriViewPasswordCell();
    }
    private DataGriViewPasswordCell PasswordCellTemplate
    {
        get { return (DataGriViewPasswordCell)this.CellTemplate; }
    }

    public bool UsePasswordCharWhenEditing
    {
        get
        {
            return PasswordCellTemplate.UsePasswordCharWhenEditing;
        }
        set
        {
            if (PasswordCellTemplate != null)
                PasswordCellTemplate.UsePasswordCharWhenEditing = value;
            if (this.DataGridView != null)
            {
                var dataGridViewRows = this.DataGridView.Rows;
                var rowCount = dataGridViewRows.Count;
                for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
                {
                    var dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
                    var dataGridViewCell = dataGridViewRow.Cells[this.Index]
                        as DataGriViewPasswordCell;
                    if (dataGridViewCell != null)
                    {
                        dataGridViewCell.UsePasswordCharWhenEditing = value;
                    }
                }
            }
        }
    }
    public class DataGriViewPasswordCell : DataGridViewTextBoxCell
    {
        public DataGriViewPasswordCell()
        {
            this.UsePasswordCharWhenEditing = true;
        }
        public bool UsePasswordCharWhenEditing { get; set; }
        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue,
            DataGridViewCellStyle dataGridViewCellStyle)
        {
            base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
            ((TextBox)this.DataGridView.EditingControl).UseSystemPasswordChar = UsePasswordCharWhenEditing;
        }
        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds,
            int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue,
            string errorText, DataGridViewCellStyle cellStyle,
            DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            formattedValue = new string('●', $"{formattedValue}".Length);
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue,
                errorText, cellStyle, advancedBorderStyle, paintParts);
        }
        public override object Clone()
        {
            var c = (DataGriViewPasswordCell)base.Clone();
            c.UsePasswordCharWhenEditing = this.UsePasswordCharWhenEditing;
            return c;
        }
    }
}

Download

You can download the full working example:

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *