0

我有一个扩展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并将其添加到我的面板时,最初为Row[0].Cell[0]引发SelectionChanged事件。即使用户从未实际单击该单元格,也会调用此事件。

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

DataGridView 初始单元格已检查

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

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

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

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

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

类图

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);
    }
}
4

3 回答 3

2

开箱即用DataGridView也会出现此问题。

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

于 2012-08-18T09:49:54.120 回答
1

好吧,当我使用表单编辑器时,我从来没有遇到过这样的事件。在绘制组件之前不会调用事件。

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

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

我希望这会有所帮助:)

~ 丹

于 2012-08-18T09:41:51.340 回答
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;
于 2012-12-26T12:00:04.323 回答