Make a DataGrid row read only based on a cell's value
(this page also shows how to work with delegates, events, and event arguments)

Unfortunately .NET doesn't support this leaving you to write your own code to do it. The C# code below shows how to disable a row based on the value of one of its cells. Actually the row is not disabled per se. The individual cells in the row are.

The code assumes you have a DataGrid formatted with a DataGridTableStyle. The table style contains 2 GridColumnStyles, one for a TextBox in column 1 and one for a data bound ComboBox in column 2. To learn more about using data bound ComboBoxes in a grid click here.

Column 1 contains a "Y" or "N" value. If it is "Y" the row is disabled and cannot be edited. If it contains an "N" it can be. Changing column 1's value from "N" to "Y" instantly disables the row.

The first step is to derive new DataGridEnableTextBoxColumn and DataGridComboBoxColumn GridColumnStyles as shown in the Listings 1 and 2 below. Both classes are derived from the standard DataGridTextBoxColumn class. The Edit method of these derived controls is overridden. Also note the EnableCellEventHandlerxxx Delegates defined at the top these classes. You can think of a delegate as a signature for a method.

When the Edit method is invoked it triggers the CheckxxxEnabled event which is declared at the top of these classes. The CheckxxxEnabled event is associated, via the delegates, with the GridColumnStyles based on the newly derived DataGridEnableTextBoxColumn and DataGridComboBoxColumn. The code to do this is as well as adding the custom ColumnStyles to the grid is shown in Listing 3 below.

Listing 4 shows the SetEnableValues procedure which acts as the handler for the CheckxxxEnabled events. This routine sets the EnableValue flag of its DataGridEnableEventArgs parameter based on the value in column 1 of the grid.

Finally all that's left is to define the Event Arguments used by the EnableCellEventHandlerxxx delegates. This is done in the DataGridEnableEventArgs class which derives from the System.EventArgs class. This can be seen in Listing 5.

Listing 1 - The derived DataGridTextBoxColumn class:

using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace ReadOnly
{
    public delegate void EnableCellEventHandlerTXT( 
         object sender, DataGridEnableEventArgs e);

    public class DataGridEnableTextBoxColumn : DataGridTextBoxColumn
    {
        public event EnableCellEventHandlerTXT CheckTXTEnabled;
	
        private int myColumn;

        public DataGridEnableTextBoxColumn(int theColumn)
        {
            myColumn = theColumn;
        }

        protected override void Edit(
            System.Windows.Forms.CurrencyManager theSource, 
            int    theRowNum, 
            System.Drawing.Rectangle theBounds, 
            bool   theReadOnlyFlag, 
            string theInstantText, 
            bool   theCellIsVisibleFlag)
            {
                bool aEnabled = true;

                if (CheckTXTEnabled != null)
                {
                    DataGridEnableEventArgs e = 
                      new DataGridEnableEventArgs(theRowNum, myColumn, aEnabled);
                    CheckTXTEnabled(this, e);
                    aEnabled = e.EnableValue;
                }

                if(aEnabled)
                    base.Edit(theSource, theRowNum, theBounds, 
                            theReadOnlyFlag, theInstantText, theCellIsVisibleFlag);
            }
    }
}

Listing 2 - The derived DataGridTextBoxColumn class:

using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace ReadOnly
{
    public delegate void EnableCellEventHandlerCBO( 
           object sender, DataGridEnableEventArgs e);

    public class DataGridComboBoxColumn: DataGridTextBoxColumn
    {
        public event EnableCellEventHandlerCBO CheckCBOEnabled;
	
        private int myColumn;

        public DataGridComboBoxColumn()
        {
        }

        protected override void Edit(
            System.Windows.Forms.CurrencyManager theSource, 
            int    theRowNum, 
            System.Drawing.Rectangle theBounds, 
            bool   theReadOnlyFlag, 
            string theInstantText, 
            bool   theCellIsVisibleFlag)
            {
                bool aEnabled = true;

                if (CheckCBOEnabled!= null)
                {
                    DataGridEnableEventArgs e = 
                       new DataGridEnableEventArgs(theRowNum, 0, aEnabled);
                    CheckCBOEnabled(this, e);
                    aEnabled = e.EnableValue;
                }

                if(aEnabled)
                    base.Edit(theSource, theRowNum, theBounds, 
                           theReadOnlyFlag, theInstantText, theCellIsVisibleFlag);
            }
    }
}

Code Listing 3 - format the DataGrid with the derived GridColumnStyles:

    // Create a aGridTableStyle to format the grid.
    DataGridTableStyle aGridTableStyle = new DataGridTableStyle(); 
    aGridTableStyle.MappingName = "myTable";

    // Create GridColumnStyles basd on our derived styles.
    // Here is the TextBox.
    DataGridEnableTextBoxColumn aCol1 = new DataGridEnableTextBoxColumn(0);
    aCol1.MappingName = "Outside_Customer";
    aCol1.HeaderText = "Outside Customer";
    aCol1.Width = 90;
    aCol1.Alignment = HorizontalAlignment.Left;
    aCol1.NullText = "N";
    aCol1.TextBox.MaxLength = 1;
    aCol1.TextBox.Enabled = true;
    aGridTableStyle.GridColumnStyles.Add(aCol1);

    // Here is the ComboBox.
    DataGridComboBoxColumn aCol2 = new DataGridComboBoxColumn();
    aCol2.MappingName = "Customer_ID";
    aCol2.HeaderText = "Customer Name";
    aCol2.Width = 90;
    aCol2.ColumnComboBox.DataSource = myDataSet.Tables["myTable"].DefaultView;
    aCol2.ColumnComboBox.DisplayMember = "Customer_Name";
    aCol2.ColumnComboBox.ValueMember = "Customer_ID";
    aCol2.NullText = "";
    aGridTableStyle.PreferredRowHeight = aCol2.ColumnComboBox.Height;
    aGridTableStyle.GridColumnStyles.Add(aCol2);

    // Add the GridColumnStyles to the GridTableStyle.
    dataGrid.TableStyles.Add(aGridTableStyle);

    // Hook our new event used to disable the TextBox and ComboBox.
    aCol1.CheckTXTEnabled += new EnableCellEventHandlerTXT(SetEnableValues);
    aCol2.CheckCBOEnabled += new EnableCellEventHandlerCBO(SetEnableValues);

Code Listing 4 - Handler for the CheckxxxEnabled events:

    private void SetEnableValues(object sender, DataGridEnableEventArgs e)
    {
        //
        // This handler disables columns based on column 1's value. 
        //
        string aValue = dataGrid[dataGrid.CurrentRowIndex, 0].ToString();
        if (aValue == null)
            aValue = "N";

        if (aValue == "Y")
            e.EnableValue = false;
        else
            e.EnableValue = true;
    }

Code Listing 5 - Event arguments signature:

    using System;

    namespace ReadOnly
    {
        //
        // Event argument signature used by the 
        // EnableCellEventHandlerxxx delegates.
        //
        public class DataGridEnableEventArgs : EventArgs
        {
            private int      myColumnNumber;
            private int      myRowNumber;
            private bool     myEnableValue;

            public DataGridEnableEventArgs(
                int theRowNumber, int theColumnNumber, bool theValue)
            {
                myRowNumber = theRowNumber;
                myColumnNumber = theColumnNumber;
                myEnableValue = theValue;
            } 

            public int ColumnNumber
            {
                get { return myColumnNumber; }
                set { myColumnNumber = value; }
            }

            public int RowNumber
            {
                get{ return myRowNumber; }
                set{ myRowNumber = value; }
            } 

            public bool EnableValue
            {
                get{ return myEnableValue; }
                set{ myEnableValue = value; }
            }
        }
    }


About TheScarms
About TheScarms


Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page


© Copyright 2016 TheScarms
Goto top of page