DataGridView在创建时为列0抛出SelectionChanged事件

时间:2012-08-18 08:53:07

标签: c# datagridview event-handling

我有一个扩展 DataGridView 的基类:

public abstract class MyDataGridView : DataGridView

然后我有一个扩展 MyDataGridView 的类。这是类定义和构造函数:

// ::FunctionGridView
public class FunctionGridView : MyDataGridView 
{
    private static int NUM_COLUMNS = 12;
    private static int NUM_ROWS = 1;

    public FunctionGridView()         
    {
        // call the method in the base class to setup the grid
        setupGridView(NUM_ROWS, NUM_COLUMNS);
    }
}

用于我的数据网格的列类型是 DataGridViewCheckBoxColumn 。以下是设置列的代码(在基类中定义):

// ::MyDataGridView
protected void setupGridView(int numRows, int numColumns)
{
    for (int i = 0; i < numColumns; i++)
    {
        DataGridViewCheckBoxColumn column = new DataGridViewCheckBoxColumn();
        column.Name = "Column" + (i + 1).ToString();
        this.Columns.Add(column);
    }
}

我想在用户单击一个单元格然后切换所选单元格的复选框时捕获 SelectionChanged 事件。回调在基类构造函数中设置如下:

// ::MyDataGridView
// initialize the controls then add the event handler
public MyDataGridView()
{            
    initialize();
    this.SelectionChanged += selectionChanged;
}

选择更改回调的定义如下:

// ::MyDataGridView
// get the checkbox _checked_ value and toggle it for the selected cell
private void handleSelectionChanged(object sender, EventArgs e)
{
    int currentRow = this.CurrentCell.RowIndex;
    int currentColumn = this.CurrentCell.ColumnIndex;
    bool cellChecked = (bool)this.Rows[currentRow].Cells[currentColumn].Value;
    this.Rows[currentRow].Cells[currentColumn].Value = !cellChecked;
}

一切都很好,除了有一个我不知道如何处理的异常......

当程序启动并构建 DataGridView 并添加到我的 Panel 时,最初会为 Row抛出 SelectionChanged 事件0]。细胞[0] 。即使用户从未真正点击过该单元格,也会调用此事件。

结果是,当我的程序启动时,第一个单元格被检查而没有任何用户点击。我的数据网格视图最终如下所示:

DataGridView Initial Cell Checked

我是否需要一种方法来确定在初始化期间是否抛出 SelectionChanged 回调,而用户单击而不是然后退出我的回调而不切换复选框值?< / p>

// ::MyDataGridView
private void selectionChanged(object sender, EventArgs e)
{
    **// if (e.isInitializing()) return;**
    ....
    ....
}

我似乎记得在Java ActionEvent 类中,你可以调用 getSource 来确保事件是由控件而不是其他来源触发的。在C#中有没有相同的东西?

============================================ ==================================

注意让我的问题变得简单我使用了基本名称并省略了大部分细节。真正的类/基类名是FunctionKeyTimer和KeyTimer(基类)。如果有帮助,这里是类图和完整的源代码:

Class Diagram

public abstract class KeyTimer : DataGridView
{
    public static int WIDTH = 640;
    public static int HEIGHT = 40;

    private bool initialCheckedValue = false;

    public KeyTimer()
    {            
        initialize();
        this.SelectionChanged += selectionChanged;
    }

    public KeyTimer(bool initialChecked)
    {            
        this.initialCheckedValue = initialChecked;
        initialize();
        this.SelectionChanged += selectionChanged;
    }

    protected void setupGridView(int numRows, int numColumns, string columnNamePrefix)
    {
        for (int i = 0; i < numColumns; i++)
        {
            DataGridViewCheckBoxColumn column = new DataGridViewCheckBoxColumn();
            column.Resizable = DataGridViewTriState.False;
            column.SortMode = DataGridViewColumnSortMode.NotSortable;
            column.Name = columnNamePrefix + (i + 1).ToString();
            this.Columns.Add(column);
        }

        for (int i = 0; i < numRows; i++)
        {
            DataGridViewRow row = new DataGridViewRow();
            this.Rows.Add(row);
        }

        foreach (DataGridViewRow row in this.Rows)
        {
            for (int i = 0; i < numColumns; i++)
            {
                row.Cells[i].Value = this.initialCheckedValue;
            }
        }
    }

    private void selectionChanged(object sender, EventArgs e)
    {
        int currentRow = this.CurrentCell.RowIndex;
        int currentColumn = this.CurrentCell.ColumnIndex;
        bool cellChecked = (bool)this.Rows[currentRow].Cells[currentColumn].Value;
        this.Rows[currentRow].Cells[currentColumn].Value = !cellChecked;
    }

    private void initialize()
    {
        this.AllowUserToDeleteRows = false;
        this.AllowUserToResizeColumns = false;
        ....
        ....
    }
}

public class FunctionKeyTimer : KeyTimer
{
    private static int NUM_COLUMNS = 12;
    private static int NUM_ROWS = 1;
    private static string COLUMN_NAME_PREFIX = "F";

    public FunctionKeyTimer()         
    {
        setupGridView(NUM_ROWS, NUM_COLUMNS, COLUMN_NAME_PREFIX);
    }
}

3 个答案:

答案 0 :(得分:2)

此问题也会在开箱即用DataGridView时发生。

标准修复是在DataBindingComplete事件处理程序中附加选择更改的处理程序。

答案 1 :(得分:1)

好吧,当我使用表单编辑器时,我从未遇到类似事件的问题。在绘制组件之前不会调用事件。

我认为这是因为您在以编程方式选中此框之前添加了事件处理程序。因此,它会被您自己的代码触发。放入一些调试消息以确定操作顺序。它可能就像移动一些函数一样简单。

除此之外,请尝试在事件监听器中打印 sender.name ,以查看它是否在用户检查和程序检查之间发生变化。

我希望有帮助:)

〜丹

答案 2 :(得分:0)

您可以使用:

DataGridViewCheckBoxColumn cb = new DataGridViewCheckBoxColumn();
cb.Name = "The Name";
cb.HeaderText = "The Name";

dataGridView1.Columns.Add(cb);
row.Cells[2].Value = true;
dataGridView1.Rows[0].Cells[6].Value = true;