如何处理顺序调用事件处理程序?

时间:2011-05-22 15:10:00

标签: c# events

在重新发明轮子之前......

这只是一个用于描述问题的示例 - 假设您有一个包含一些数据集合的后端,而前端则显示该集合的一个项目。

在后端,我有ItemIndex - 每当它发生变化时,它都会激活OnScroll事件。

我也有AddNewItem方法,它在集合的末尾添加了新项。方法的结尾是调用OnNewItem事件处理程序。

这里有一个捕获 - 在AddNewItem我必须更改ItemIndex,它会触发OnScroll。 (!)OnScroll和OnNewItem的接收者之一,如果前端显示所选项目。

在这种情况下,它被调用两次(不好)。一种解决方案是改变item_index而不是ItemIndex,这样可以防止OnScroll,但我不喜欢它,因为ItemIndex不再作为黑盒子了。

顺序触发事件是否存在已建立的模式,并且仅发送“重要”事件(此处:OnNewItem会覆盖OnScroll)?我的想法是定义一个事件范围,然后不是直接发送事件,只需将它们注册为发送,并在范围结束时对它们进行排序并发送所需的事件。

一般来说 - 问题 - 我应该如何处理潜在的顺序事件触发。使用内部设备来避免发送冗余事件?忽略开销? ...?

3 个答案:

答案 0 :(得分:2)

答案似乎很明显,但我很容易错过一些东西:

private bool IsAdding { get; set; }
private int item_index;
private IList m_collection;

public void AddNewItem(object item)
{
    if (item == null)
    {
        throw new Exception("Cannot add null item."); // little bit of contracting never hurts
    }

    m_collection.Add(item);
    IsAdding = true;
    ItemIndex = collection.Count - 1; //I'm just making assumptions about this piece but it is not important how you decide what your index is to answer the question

    if (OnNewItem != null)
    {
       OnNewItem(this, EventArgs.Empty); 
    }
}

public int ItemIndex
{
   get { return item_index =; }
   set
   {
       item_index = value;
       if (!IsAdding && OnScroll != null) //won't double fire event thanks to IsAdding
       {
           OnScroll(this, EventArgs.Empty);
       }
       IsAdding = false; //need to reset it
   }
}

我要注意的一件事是你提到的只是直接改变item_index,但不会有黑盒行为。好的黑盒子一切都很好......但是这个术语只适用于与我们讨论过的这个类相互作用的对象。

你应该感到有权使用你自己的课程内部。黑盒内的物品本身并不好OOP。如果你这样做,那么你的课可能有设计问题,应该将它分成多个类。

答案 1 :(得分:2)

一种解决方案是使用某种形式的“闩锁”。更新时,您通过帮助程序执行UI操作,该帮助程序设置一个标记,表示“嘿,我处于特殊状态!”。然后,在引发事件时,检查是否设置了锁存器 - 如果是,则跳过提升这些事件。

这基本上是马修发布的一个非常简单的通用版本。根据具体情况,设置标志可能绰绰有余。

Jeremy Miller's explanation is worth reading

答案 2 :(得分:0)

您可以将两个事件都指向一个函数。该功能可以确定发件人并执行适当的操作。