Subbu
Subbu

Reputation: 618

Show CheckBox column for Nullable<bool> properties in DataGridView

After some considerable searching I haven't been able to find a solution to this issue. I have successfully set the DataSource of a DatagridView using a list as follows.

The class

public class ChannelInfo
{
    [Browsable(false)]
    [DisplayName("ChannelId")]
    public int channelId { get; set; }
    [DisplayName("Channel")]
    public string sysName { get; set; }
    [DisplayName("Display Name")]
    public string dispName { get; set; }
    [DisplayName("Unit")]
    public string unit { get; set; }
    [DisplayName("Divide By")]
    public int divideBy { get; set; }
    [DisplayName("YAxis")]
    public string yAxis { get; set; }
    [DisplayName("Min Scale")]
    public int scaleMin { get; set; }
    [DisplayName("Max Scale")]
    public int scaleMax { get; set; }
    [DisplayName("Colour")]
    public string colour { get; set; }
    [DisplayName("Set Point")]
    public double setPoint { get; set; }
    [DisplayName("Limit(+/-)")]
    public double? limit { get; set; }
    [DisplayName("MKT")]
    public bool? IncludeInMKT { get; set; }
    /// <summary>
    /// Default constructor
    /// </summary>
    public ChannelInfo()
    {

    }

    /// <summary>
    /// Copy constructor to create a copy of another object
    /// </summary>
    /// <param name="ci"> and object of the type ChannelInfo whos copy is to be created</param>
    public ChannelInfo(ChannelInfo ci)
    {
        channelId = ci.channelId;
        sysName = ci.sysName;
        dispName = ci.dispName;
        unit = ci.unit;
        divideBy = ci.divideBy;
        yAxis = ci.yAxis;
        scaleMin = ci.scaleMin;
        scaleMax = ci.scaleMax;
        colour = ci.colour;
        setPoint = ci.setPoint;
        limit = ci.limit;
        IncludeInMKT = ci.IncludeInMKT;
    }
}

setting the data-source of the grid

static List<ChannelInfo> chInfoList;
dgvChannels.DataSource = chInfoList;

The type of the final column of the data-grid is set to DataGridViewCheckBoxColumn using the designer. The data-grid displays all the data fine except the last boolean field IncludeInMkt. It shows the text values (True/False) whereas, I expect it to be shown as a check box with the corresponding values in the chInfoList. I have also set the TrueValue to True and FalseValue to False in the designer.

Where am I going wrong, kindly suggest.

Upvotes: 1

Views: 734

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125197

DataGridView will generate DataGridViewCheckBoxColumn for bool properties. But for bool? properties it will generate DataGridViewTextBoxColumn.

You can fix it in design-time or run-time by replacing the generated column with a DataGridViewCheckBoxColumn and setting its ThreeState property to true.

Example - Show CheckBox for Nullable<bool> in DataGridView

The following function replaces generated columns for bool? properties with tree-state check-box columns:

public void UseCheckBoxForNullableBool(DataGridView g)
{
    g.Columns.Cast<DataGridViewColumn>()
        .Where(x => x.ValueType == typeof(bool?))
        .ToList().ForEach(x =>
        {
            var index = x.Index;
            g.Columns.RemoveAt(index);
            var c = new DataGridViewCheckBoxColumn();
            c.ValueType = x.ValueType;
            c.ThreeState = true;
            c.DataPropertyName = x.DataPropertyName;
            c.HeaderText = x.HeaderText;
            c.Name = x.Name;
            g.Columns.Insert(index, c);
        });
}

enter image description here

In above form, I've used the following model:

public class Test
{
    public int MyProperty1 { get; set; }
    public bool? MyProperty2 { get; set; }
}

And applied the UseCheckBoxForNullableBool to change the generated column for bool? property to a tree-state check-box column:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    this.dataGridView1.DataSource = new BindingList<Test>() {
        new Test(){ MyProperty1 = 1, MyProperty2= null},
        new Test(){ MyProperty1 = 2, MyProperty2= true},
        new Test(){ MyProperty1 = 3, MyProperty2= false},
    };
    UseCheckBoxForNullableBool(dataGridView1);
}

Note: If you are interested to show ComboBox for bool or bool? columns, take a look at this post which does the same for bool properties and change it a bit to support bool? as well.

Upvotes: 1

Related Questions