将多个checkedListbox添加到datagrid View的列

时间:2011-01-18 13:11:57

标签: c# winforms datagridview

因为我们可以将单个复选框添加到datagrid视图列的列,但是可以将选中的列表框添加到datagrid视图,目的是让一个单元格具有多个复选框。

我们如何添加它们?

我们如何访问其属性,例如文本和已检查?

得到了一些答案,但我无法理解 http://social.msdn.microsoft.com/Forums/en/winformsdatacontrols/thread/6c68a44c-c4ab-4caf-94e9-249ec63a90d0

2 个答案:

答案 0 :(得分:2)

在使用此代码之前,请阅读本答案底部的评论。

<小时/> 根据问题我们如何访问此CheckListBox DataGridView Column 中的文字和复选框:

public class CheckedListBoxColumn : DataGridViewColumn
{
    public CheckedListBoxColumn()
        : base(new CheckedListBoxCell())
    {
    }

    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }
        set
        {
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(CheckedListBoxCell)))
            {
                throw new InvalidCastException("Must be a CheckedListBoxCell");
            }
            base.CellTemplate = value;
        }
    }
}

public class CheckedListBoxCell : DataGridViewCell
{
    public CheckedListBoxCell()
        : base()
    {

    }

    public override void InitializeEditingControl(int rowIndex, object
        initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // Set the value of the editing control to the current cell value.  
        base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);
        CheckedListBoxEditingControl ctl =
            DataGridView.EditingControl as CheckedListBoxEditingControl;
        InitializeCheckedListBox(ctl, (ICollection)this.FormattedValue);
    }
    private void InitializeCheckedListBox(CheckedListBox ctrl, ICollection value)
    {
        ctrl.Items.Clear();
        foreach (object obj in value)
        {
            ctrl.Items.Add(obj.ToString());
        }
        ctrl.Tag = this.Value;
    }
    public override Type EditType
    {
        get
        {
            return typeof(CheckedListBoxEditingControl);
        }
    }
    protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
    {
        if (value == null)
        {
            return new List<object>();
        }
        return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
    }
    public override Type FormattedValueType
    {
        get
        {
            return typeof(ICollection);
        }
    }
    public override Type ValueType
    {
        get
        {
            return typeof(ICollection);
        }
    }
    private CheckedListBox internalControl;

    protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        graphics.FillRectangle(new SolidBrush(cellStyle.BackColor), cellBounds);

        if (internalControl == null)
        {
            internalControl = new CheckedListBox();
        }
        internalControl.Items.Clear();
        ICollection collection = value as ICollection;
        if (collection != null)
        {
            foreach (object obj in collection)
            {
                internalControl.Items.Add(obj);
            }
            Bitmap bmp = new Bitmap(cellBounds.Width, cellBounds.Height);
            internalControl.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
            graphics.DrawImage(bmp, cellBounds, new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
        }
    }
    protected override void OnClick(DataGridViewCellEventArgs e)
    {
        this.DataGridView.BeginEdit(false);
        base.OnClick(e);
    }
}

class CheckedListBoxEditingControl : CheckedListBox, IDataGridViewEditingControl
{
    DataGridView dataGridView;
    private bool valueChanged = false;
    int rowIndex;

    public CheckedListBoxEditingControl()
    {

    }

    // Implements the IDataGridViewEditingControl.EditingControlFormattedValue   
    // property.  
    public object EditingControlFormattedValue
    {
        get
        {
            return this.Tag;
        }
        set
        {
            //  this.Tag = value;  
        }
    }

    // Implements the   
    // IDataGridViewEditingControl.GetEditingControlFormattedValue method.  
    public object GetEditingControlFormattedValue(
        DataGridViewDataErrorContexts context)
    {
        return EditingControlFormattedValue;
    }

    // Implements the   
    // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.  
    public void ApplyCellStyleToEditingControl(
        DataGridViewCellStyle dataGridViewCellStyle)
    {
        this.Font = dataGridViewCellStyle.Font;
        this.ForeColor = dataGridViewCellStyle.ForeColor;
        this.BackColor = dataGridViewCellStyle.BackColor;
    }

    // Implements the IDataGridViewEditingControl.EditingControlRowIndex   
    // property.  
    public int EditingControlRowIndex
    {
        get
        {
            return rowIndex;
        }
        set
        {
            rowIndex = value;
        }
    }

    // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey   
    // method.  
    public bool EditingControlWantsInputKey(
        Keys key, bool dataGridViewWantsInputKey)
    {
        // Let the DateTimePicker handle the keys listed.  
        switch (key & Keys.KeyCode)
        {
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
            case Keys.Right:
            case Keys.Home:
            case Keys.End:
            case Keys.PageDown:
            case Keys.PageUp:
                return true;
            default:
                return !dataGridViewWantsInputKey;
        }
    }

    // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit   
    // method.  
    public void PrepareEditingControlForEdit(bool selectAll)
    {
        // No preparation needs to be done.  
    }

    // Implements the IDataGridViewEditingControl  
    // .RepositionEditingControlOnValueChange property.  
    public bool RepositionEditingControlOnValueChange
    {
        get
        {
            return false;
        }
    }

    // Implements the IDataGridViewEditingControl  
    // .EditingControlDataGridView property.  
public DataGridView EditingControlDataGridView
{
    get
    {
        return dataGridView;
    }
    set
    {
        dataGridView = value;
    }
}

// Implements the IDataGridViewEditingControl  
// .EditingControlValueChanged property.  
public bool EditingControlValueChanged
{
    get
    {
        return valueChanged;
    }
    set
    {
        valueChanged = value;
    }
}

// Implements the IDataGridViewEditingControl  
// .EditingPanelCursor property.  
public Cursor EditingPanelCursor
{
    get
    {
        return base.Cursor;
    }
}
}    

一篇有趣的博客文章介绍了此课程的问题:http://dotnetgenetics.blogspot.com.au/2014/01/custom-checkedlistbox-datagridview.html

在CheckedListBoxCell类中添加一个属性以检索已检查的项目:

 public ICollection CheckedItems
 {
    get
    {
        if (internalControl == null)
            return null;
        else
        {
            if (internalControl != null)
            {
                if (internalControl.CheckedItems.Count > 0)
                {
                    return internalControl.CheckedItems;
                }
                else
                {
                    if ((CheckedListBox)this.DataGridView.Rows[RowIndex].Cells[ColumnIndex].DataGridView.EditingControl != null)
                    {
                        CheckedListBox checks = (CheckedListBox)this.DataGridView.Rows[RowIndex].Cells[ColumnIndex].DataGridView.EditingControl;
                        if (checks.CheckedItems.Count > 0)
                            return checks.CheckedItems;
                        else
                            return null;
                    }
                    else
                        return null;
                }
            }
            else
            {
                return null;
            }
        }
    }
}  

这是获取已检查项目的方法。

 private void btnShow_Click(object sender, EventArgs e)  
 {  
   StringBuilder builder = new StringBuilder();  
   foreach (DataGridViewRow item in dgCheckListColumn1.Rows)  
   {  
     DataGridViewCell cell = item.Cells[1];  
     if (((cell as CheckedListBoxCell).CheckedItems != null))  
     {  
       if (((cell as CheckedListBoxCell).CheckedItems.Count > 0))  
       {  
         foreach (var checkItem in ((cell as CheckedListBoxCell).CheckedItems))  
         {  
           builder.AppendLine(String.Format("Row {0} : item: {1}", item.Index + 1, checkItem.ToString()));  
         }  
         builder.AppendLine(Environment.NewLine);  
       }   
     }  
   }  
   MessageBox.Show("Checked Items: \n" + builder.ToString());  
 }  

<小时/> 我对这一切的看法是 - 它的垃圾 - 看起来像垃圾,它的行为就像垃圾......甚至感觉垃圾:

enter image description here

<小时/> 恕我直言,它更好地利用DataGridView的单元格点击事件并弹出一个CheckedListbox:

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == 1)
    {
        int RowHeight1 = DataGridView1.Rows[e.RowIndex].Height;
        Rectangle CellRectangle1 = DataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);

        CellRectangle1.X += DataGridView1.Left;
        CellRectangle1.Y += DataGridView1.Top + RowHeight1;

        Point DisplayPoint1 = PointToScreen(new Point(CellRectangle1.X, CellRectangle1.Y));
        checkedListBox1.Left = CellRectangle1.X;
        checkedListBox1.Top = CellRectangle1.Y;
    }
}

enter image description here

答案 1 :(得分:0)

您可以通过创建自定义DataGridView列来完成此操作。网上有很多文章证明了这一点; here's one example。将复选框公开为属性以访问其属性。