WinForms中不会触发事件处理程序

时间:2017-06-28 20:38:50

标签: c# winforms event-handling

我正在努力解决事件。我有一个用户控件,我想从用户双击时返回ID字段。这是我的用户控件代码:

// inside the user control class:
public event EventHandler<SelectedItemEventArgs> ItemHasBeenSelected;

public class SelectedItemEventArgs : EventArgs
{
    public int SelectedChoice { get; set; }
}

private void DataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
    var handler = ItemHasBeenSelected;
    if (e.RowIndex >= 0 && e.RowIndex < DataGridView.RowCount)
    {
        // 6 == id column
        int choice = (int)DataGridView[6, First ? 0 : e.RowIndex].Value;
        if (handler != null)
            handler(this, new SelectedItemEventArgs { SelectedChoice = hoice });
    }
}

在调用程序中:

public Main
{ 
    InitializeComponent();
    uc.ItemHasBeenSelected += uc_ItemHasBeenSelected;
}

private void uc_ItemHasBeenSelected(object sender, FindControl.SelectedItemEventArgs e)
{
    var value = e.SelectedChoice;
    currentVal = value;
}

我一直得到我的事件处理程序(var handler)= null。我知道我必须遗漏一些东西,但它已经过了很多个小时而我却无法找到它。如果可以,请帮忙。

2 个答案:

答案 0 :(得分:1)

根据尼克回答的评论,Missy要求我发布举办活动的最佳做法。

我简化了您的代码来说明:

public event EventHandler<SelectedItemEventArgs> ItemHasBeenSelected;

public class SelectedItemEventArgs : EventArgs { }

private void OnItemHasBeenSelected()
{
    var handler = this.ItemHasBeenSelected;
    if (handler != null)
    {
        handler(this, new SelectedItemEventArgs());
    }
}

这里要注意的关键是作业var handler = this.ItemHasBeenSelected;。这会生成委托的副本,因此会附加处理程序,这意味着如果this.ItemHasBeenSelected发生任何事情,则不会影响handler

与以下内容比较:

private void OnItemHasBeenSelected()
{
    if (this.ItemHasBeenSelected != null)
    {
        this.ItemHasBeenSelected(this, new SelectedItemEventArgs());
    }
}

在这种情况下,在检查this.ItemHasBeenSelected != null之后但在调用this.ItemHasBeenSelected(this, new SelectedItemEventArgs());之前有一个错误,另一个线程(或者在更复杂的情况下甚至是异步代码)可以删除处理程序,以便后续调用将失败,因为委托现在将为null

使用var handler = this.ItemHasBeenSelected;分配可以避免这种情况。

答案 1 :(得分:0)

首先,创建一个事件委托:

public delegate void ItemHasBeenSelected (object sender, SelectedItemEventArgs e);

实例化事件委托:

public event ItemHasBeenSelected SelectedItem;

如果您想举起活动:

this.SelectedItem(this, new SelectedItemEventArgs { SelectedChoice = choice })

完成此设置后,您可以将事件绑定到事件处理程序:

this.SelectedItem += main.uc_ItemHasBeenSelected;

如果要在表单中定义委托,而不是您希望事件处理程序的位置,则需要将this值传递到表单的构造函数中并将其存储在表格中的变量。在分配事件处理程序时引用该变量。

从控件中定义委托,并在为事件分配处理程序时从主程序中引用委托。

Control.SelectedItem += this.uc_ItemHasBeenSelected;