如何删除事件处理程序?

时间:2014-08-14 09:22:25

标签: c# silverlight

/

/First Version        
public Sniper(string sourceTableName, ComboBox targetComboBox)
{
    proxy.GetBasicEntryAsync(sourceTableName);
    proxy.GetBasicEntryCompleted += GetBasicEntryCompleted;
}
void GetBasicEntryCompleted(object sender, EventArgs e)
{
    proxy.GetBasicEntryCompleted -= OnBasicEntryCompleted;

    if (e.Result.Any())
    {
        targetComboBox.ItemsSource = e.Result.ToList();
        targetComboBox.DisplayMemberPath = "Description";
        targetComboBox.SelectedItem = "ID";
    }
    else
    {
        targetComboBox.ItemsSource = null;
    }
}

HTML对象元素与所有支持的Web浏览器兼容,并为Silverlight.js嵌入技术提供了基础。 Silverlight.js嵌入函数最终生成HTML对象元素,并公开对象元素公开的所有功能。这个通用基础使您能够结合两种嵌入技术。

>     //Second Version
    >     public Sniper(string sourceTableName, ComboBox targetComboBox)
    >     {
    >         proxy.GetBasicEntryAsync(sourceTableName);
    >         proxy.GetBasicEntryCompleted += (sender, e) => //This the event
    >         {
    >             //  proxy.GetBasicEntryCompleted -= OnBasicEntryCompleted; I want to perform this action in this lambda expression.
    >             if (e.Result.Any())
    >             {
    >                 targetComboBox.ItemsSource = e.Result.ToList();
    >                 targetComboBox.DisplayMemberPath = "Description";
    >                 targetComboBox.SelectedItem = "ID";
    >             }
    >             else
    >             {
    >                 targetComboBox.ItemsSource = null;
    >             }
    >         };

>     }

2 个答案:

答案 0 :(得分:2)

首先给你的处理程序一个名字,然后在某个地方保存unsubscribtion(例如在基类上的一个Action - 你也可能更喜欢IDisposable但是遗憾的是在C#中没有像这样的ann.interface-implementation ,所以我选择动作):

private Action _removeSubs;

public Sniper(string sourceTableName, ComboBox targetComboBox)
    {
        proxy.GetBasicEntryAsync(sourceTableName);
        Action <object, EventArgs> _handler = (sender, e) =>
        {
            if (e.Result.Any())
            {
                targetComboBox.ItemsSource = e.Result.ToList();
                targetComboBox.DisplayMemberPath = "Description";
                targetComboBox.SelectedItem = "ID";
            }
            else
            {
                targetComboBox.ItemsSource = null;
            }
        };
        proxy.GetBasicEntryCompleted += handler;
        _removeSubs = () => proxy.GetBasicEntryCompleted -= handler;
    }

然后如果你可以这样删除它:

_removeSubs();

BTW:您的proxy似乎是全局或本地的 - 所以您也可以存储处理程序/操作。

Oliver提到的Methoad方法也适用于这种情况,但是当你需要在你的手中使用targetComboBox时,你需要捕获/存储一些 - 这就是为什么我会推荐 local < / em>方法。

答案 1 :(得分:1)

无法删除匿名lambdas事件处理程序。而是将lambda放入普通方法中。你可以拨打proxy.GetBasicEntryCompleted -= MyMethod;

以下是一个示例:

private void OnBasicEntryCompleted(object sender, BasicEntryEventArgs e)
{
    if (e.Result.Any())
    {
        e.TargetComboBox.ItemsSource = e.Result.ToList();
        e.TargetComboBox.DisplayMemberPath = "Description";
        e.TargetComboBox.SelectedItem = "ID";
    }
    else
    {
        e.TargetComboBox.ItemsSource = null;
    }

    var proxy = (Proxy)sender;

    proxy.GetBasicEntryCompleted -= OnBasicEntryCompleted;
}

public void Sniper(string sourceTableName, ComboBox targetComboBox)
{
    proxy.GetBasicEntryCompleted += OnBasicEntryCompleted;
    proxy.GetBasicEntryAsync(sourceTableName, targetComboBox);
}

另请注意,在调用引发事件的方法之前,您始终会订阅事件。否则它可能会发生,由于比赛条件不会被通知。

如果你调用这个异步方法,那么问题就在于将在哪个线程中引发完成的事件?如果它发生在运行异步任务的线程中,则不会在gui线程内,并且不建议在其他线程内操作gui对象(如组合框)。因此,可以在e.TargetComboBox.Invoke()调用中封装您对组合框的访问。