c# - DataGridView CheckBox 单元格/列事件

标签 c# datagridview checkbox event-handling click

如何订阅 DataGridView 的 CheckBoxColumn 中 CheckBox 的事件处理程序,类似于常规 CheckBox 的 CheckChanged 或 Click 事件处理程序?我在我的应用程序的多个数据网格中有一个或多个列,我想为此执行此操作。

我查看了 CellContentClick 和 CellClick,但它们看起来完全不优雅,因为它们会在数据网格中的每次点击时触发,而不仅仅是对感兴趣的 Cell 或 CheckBox 触发。

最佳答案

下面的解决方案来自于大量阅读 MSDN 文档,以及在这里和 CodeProject 上的一些切线线程中的一点运气。

想法是创建一个派生自 DataGridViewCheckBoxCell 的类,该类包含一个随 ContentClick 一起触发的处理程序。这对于一个 DataGridView 来说似乎开销很大,但我的应用程序有很多 DataGridView,因此这段代码是可重用的,从而节省了时间。

/// <summary>
/// DataGridView cell class for check box cells with a OnContentClick event handler.
/// </summary>
public class DataGridViewEventCheckBoxCell : DataGridViewCheckBoxCell
{
    /// <summary>
    /// Event handler for OnContentClick event.
    /// </summary>
    protected EventHandler<DataGridViewCellEventArgs> ContentClickEventHandler { get; set; }

    /// <summary>
    /// Empty constructor. Required. Used by Clone mechanism
    /// </summary>
    public DataGridViewEventCheckBoxCell()
        : base()
    { }

    /// <summary>
    /// Pass through constructor for threeState parameter.
    /// </summary>
    /// <param name="threeState">True for three state check boxes, True, False, Indeterminate.</param>
    public DataGridViewEventCheckBoxCell(bool threeState)
        : base(threeState)
    { }

    /// <summary>
    /// Constructor to set the OnContentClick event handler.  
    /// Signature for handler should be (object sender, DataGridViewCellEventArgs e)
    /// The sender will be the DataGridViewCell that is clicked.
    /// </summary>
    /// <param name="handler">Handler for OnContentClick event</param>
    /// <param name="threeState">True for three state check boxes, True, False, Indeterminate.</param>
    public DataGridViewEventCheckBoxCell(EventHandler<DataGridViewCellEventArgs> handler, bool threeState)
        : base(threeState)
    {
        ContentClickEventHandler = handler;
    }

    /// <summary>
    /// Clone method override.  Required so CheckEventHandler property is cloned.
    /// Individual DataGridViewCells are cloned from the DataGridViewColumn.CellTemplate
    /// </summary>
    /// <returns></returns>
    public override object Clone()
    {
        DataGridViewEventCheckBoxCell clone = (DataGridViewEventCheckBoxCell)base.Clone();
        clone.ContentClickEventHandler = ContentClickEventHandler;
        return clone;
    }

    /// <summary>
    /// Override implementing OnContentClick event propagation 
    /// </summary>
    /// <param name="e">Event arg object, which contains row and column indexes.</param>
    protected override void OnContentClick(DataGridViewCellEventArgs e)
    {
        base.OnContentClick(e);
        if (ContentClickEventHandler != null)
            ContentClickEventHandler(this, e);
    }

    /// <summary>
    /// Override implementing OnContentDoubleClick event propagation 
    /// Required so fast clicks are handled properly.
    /// </summary>
    /// <param name="e">Event arg object, which contains row and column indexes.</param>
    protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
    {
        base.OnContentDoubleClick(e);
        if (ContentClickEventHandler != null)
            ContentClickEventHandler(this, e);
    }
}

因为我希望能够从列类中引用这个单元格类,所以我还实现了一个从 DataGridViewCheckBoxColumn 派生的类:

/// <summary>
/// DataGridView column class for a check box column with cells that have an OnContentClick handler.
/// </summary>
public class DataGridViewEventCheckBoxColumn : DataGridViewCheckBoxColumn
{
    /// <summary>
    /// Empty constructor.  Pass through to base constructor
    /// </summary>
    public DataGridViewEventCheckBoxColumn()
        : base()
    { }

    /// <summary>
    /// Pass through to base constructor with threeState parameter
    /// </summary>
    /// <param name="threeState">True for three state check boxes, True, False, Indeterminate.</param>
    public DataGridViewEventCheckBoxColumn(bool threeState)
        : base(threeState)
    { }

    /// <summary>
    /// Constructor for setting the OnContentClick event handler for the cell template.
    /// Note that the handler will be called for all clicks, even if the DataGridView is ReadOnly.
    /// For the "new" state of the checkbox, use the EditedFormattedValue property of the cell.
    /// </summary>
    /// <param name="handler">Event handler for OnContentClick.</param>
    /// <param name="threeState">True for three state check boxes, True, False, Indeterminate.</param>
    public DataGridViewEventCheckBoxColumn(EventHandler<DataGridViewCellEventArgs> handler, bool threeState)
        : base(threeState)
    {
        CellTemplate = new DataGridViewEventCheckBoxCell(handler, threeState);
    }
}

修剪掉多余的代码,我是这样使用它的:

public void AddCheckBoxColumn(DataGridView grid, EventHandler<DataGridViewCellEventArgs> handler, bool threeState)
{
   grid.Columns.Add(new DataGridViewEventCheckBoxColumn(handler, threeState));
}

列类可以去掉,可以这样使用:

public void AddCheckBoxColumn(DataGridView grid, EventHandler<DataGridViewCellEventArgs> handler, bool threeState)
{
   DataGridViewCheckBoxColumn column = new DataGridViewCheckBoxColumn(threeState);
   column.CellTemplate = new DataGridViewEventCheckBoxCell(handler, threeState);
   grid.Columns.Add(column);
}

这是一个示例事件处理程序。数据网格中另一列的状态根据该列的值和 WasReleased 属性中的某些状态信息有条件地更新。 DataGridView 的 DataSource 是 Specimen 对象的集合,所以每一行的 DataBoundItem 都是一个 Specimen。 Specimen 类是特定于应用程序的,但它具有属性 OnHold,由此列显示; IsReleased,由另一列显示;并已发布。

    public static void OnHoldCheckClick(object sender, DataGridViewCellEventArgs e)
    {
        if (sender is DataGridViewEventCheckBoxCell)
        {
            DataGridViewEventCheckBoxCell cell = sender as DataGridViewEventCheckBoxCell;

            if (!cell.ReadOnly)
            {
                // The rows in the DataGridView are bound to Specimen objects
                Specimen specimen = (Specimen)cell.OwningRow.DataBoundItem;
                // Modify the underlying data source
                if ((bool)cell.EditedFormattedValue)
                    specimen.IsReleased = false;
                else if (specimen.WasReleased)
                    specimen.IsReleased = true;
                // Then invalidate the cell in the other column to force it to redraw
                DataGridViewCell releasedCell = cell.OwningRow.Cells["IsReleased"];
                cell.DataGridView.InvalidateCell(releasedCell);
            }
        }
    }

好的风格可能会将事件处理程序中的一些代码向下推送到 Specimen 类中的方法中。

关于c# - DataGridView CheckBox 单元格/列事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13354277/

相关文章:

c# - DataGridViewColumnHeader 加粗

jquery - 从周围标签中通过标签文本选择复选框?

c# - 将同步代码包装到异步调用中

c# - 如何在 SqlCommand 中设置未命名的 SQL 参数

c# - 在重定向之前设置 Viewbag

c# - 如何在 C# 中的同一个 Datagridview 中添加新的 Datagridview 行和现有行

c# - 使用 DataGridView、DataTable 和 DataAdapter 的 CRUD 操作 - 无法向 DataGridView 添加新行

javascript - 如何为未知数量的复选框实现全选按钮

javascript - AngularJs:删除项目后取消选中复选框

c# - Microsoft Bot Framework 中带有 FormBuilder 的自定义字段