将事件附加到DataGridView单元格的TextBox底层

时间:2011-03-25 08:35:04

标签: c# winforms .net-2.0

有没有办法获得DataGridView单元的底层控件? 我想附加普通的texbox事件来捕获击键并捕获值的变化。

所以我有4列,每列包含多个单元格,一行中的所有单元格应根据其类型以不同的方式处理。

基本上我只需要在编辑单元格时触发我的事件。

3 个答案:

答案 0 :(得分:9)

订阅DataGridView.EditingControlShowing活动,然后订阅您需要的TextBox活动。


TextBox.KeyDown的示例:

void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    var txtBox = e.Control as TextBox;
    if (txtBox != null)
    {
        // Remove an existing event-handler, if present, to avoid 
        // adding multiple handlers when the editing control is reused.
        txtBox.KeyDown -= new KeyEventHandler(underlyingTextBox_KeyDown);

        // Add the event handler. 
        txtBox.KeyDown += new KeyEventHandler(underlyingTextBox_KeyDown);
    }
}

void underlyingTextBox_KeyDown(object sender, KeyEventArgs e)
{
    // ...
}

修改

现在代码更正确,因为它遵循MSDN上的建议:

  

DataGridView控件托管一个   一次编辑控件,然后重复使用   每当单元格编辑控件   类型不会在编辑之间更改。   将事件处理程序附加到   因此,您必须编辑控件   采取预防措施,以避免附着   多次使用相同的处理程序。至   避免这个问题,删除处理程序   在你附上之前的事件   事件的处理程序。这将   如果处理程序是,防止重复   已经附在活动上,但是   否则将无效。对于   更多信息,请参阅示例代码   在里面   DataGridViewComboBoxEditingControl   课程概述。

编辑2:

根据评论:

TextChanged之前调用

EditingControlShowing事件,然后再调用它。

您可以使用此技巧区分两个调用:

void txtBox_TextChanged(object sender, EventArgs e)
{
    var txtBox = (TextBox)sender;
    if (txtBox.Focused)
    {
        // second call (after EditingControlShowing) the TextBox is focused
    }
    else
    {
        // first call (before EditingControlShowing) the TextBox is not focused
    }
}

答案 1 :(得分:0)

您可以使用 EditingControlShowing 事件

执行此操作
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is TextBox)
            {
                (e.Control as TextBox).KeyDown += new KeyEventHandler(Form1_KeyDown);
                //add as you require
            }
        }

        void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            // your code here
        }

答案 2 :(得分:0)

感谢@digEmAll我能够将事件注册到基础TextBox,但是这种方法处理的事件非常奇怪,必须采取一些预防措施。

我注意到在EditControlShowing之前触发了新单元格文本框的TextChanged事件。它的结果是最初为单元格注册的触发处理程序只是离开了将作为发送者聚焦的字段。这就是为什么所有事件都应该在休假时取消注册以避免这种行为。

我的问题的最终解决方案:

    void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {

        if (e.Control is TextBox)
        {

            DataGridView dgv = sender as DataGridView;
            DataGridViewColumn dgvCol= dgv.CurrentCell.OwningColumn;

            TextBox tb = (TextBox)e.Control;

            foreach (cFieldLayoutType fieldLayout in FieldLayouts)
            {

                string context = dgvCol.Name.Substring(dgvCol.Name.LastIndexOf(".") + 1);

                if (context == fieldLayout.columnName)
                {
                    //See URL to check why it is done this way: http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.editingcontrolshowing.aspx

                    KeyPressEventHandler kpehAmount = new KeyPressEventHandler(oTextBoxAmount_KeyPress);                        
                    KeyPressEventHandler kpehDecimal = new KeyPressEventHandler(oTextBoxDecimal_KeyPress);
                    KeyPressEventHandler kpehDate = new KeyPressEventHandler(oTextBoxDate_KeyPress);
                    EventHandler textChangedHandlerAmount = new EventHandler(oTextBoxAmount_TextChanged);

                    tb.Leave += new EventHandler(textBox_DeregisterCellEventsOnLeave);                        
                    switch (fieldLayout.Type)
                    {
                        case cFieldType.amount:
                            {
                                tb.KeyPress += kpehAmount;

                                tb.TextChanged += textChangedHandlerAmount;
                                break;
                            }
                        case cFieldType.numeric:
                            {
                                tb.KeyPress += kpehDecimal;
                                break;
                            }
                        case cFieldType.date:
                            {
                                tb.KeyPress += kpehDate;
                                break;
                            }
                        case cFieldType.text:
                            {
                                break;
                            }
                    }
                }
            }
        }
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void textBox_DeregisterCellEventsOnLeave(object sender, EventArgs e)
    {
        TextBox tb = (TextBox)sender;

        KeyPressEventHandler kpehAmount = new KeyPressEventHandler(oTextBoxAmount_KeyPress);
        KeyPressEventHandler kpehDecimal = new KeyPressEventHandler(oTextBoxDecimal_KeyPress);
        KeyPressEventHandler kpehDate = new KeyPressEventHandler(oTextBoxDate_KeyPress);
        EventHandler textChangedHandlerAmount = new EventHandler(oTextBoxAmount_TextChanged);
        EventHandler textBoxDeregisterOnLeave = new EventHandler(textBox_DeregisterCellEventsOnLeave);

        tb.KeyPress -= kpehAmount;
        tb.KeyPress -= kpehDate;
        tb.KeyPress -= kpehDecimal;
        tb.TextChanged -= textChangedHandlerAmount;
        tb.Leave -= textBoxDeregisterOnLeave;       
    }