在重新发明轮子之前......
这只是一个用于描述问题的示例 - 假设您有一个包含一些数据集合的后端,而前端则显示该集合的一个项目。
在后端,我有ItemIndex - 每当它发生变化时,它都会激活OnScroll事件。
我也有AddNewItem方法,它在集合的末尾添加了新项。方法的结尾是调用OnNewItem事件处理程序。
这里有一个捕获 - 在AddNewItem我必须更改ItemIndex,它会触发OnScroll。 (!)OnScroll和OnNewItem的接收者之一,如果前端显示所选项目。
在这种情况下,它被调用两次(不好)。一种解决方案是改变item_index而不是ItemIndex,这样可以防止OnScroll,但我不喜欢它,因为ItemIndex不再作为黑盒子了。
顺序触发事件是否存在已建立的模式,并且仅发送“重要”事件(此处:OnNewItem会覆盖OnScroll)?我的想法是定义一个事件范围,然后不是直接发送事件,只需将它们注册为发送,并在范围结束时对它们进行排序并发送所需的事件。
一般来说 - 问题 - 我应该如何处理潜在的顺序事件触发。使用内部设备来避免发送冗余事件?忽略开销? ...?
答案 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操作,该帮助程序设置一个标记,表示“嘿,我处于特殊状态!”。然后,在引发事件时,检查是否设置了锁存器 - 如果是,则跳过提升这些事件。
这基本上是马修发布的一个非常简单的通用版本。根据具体情况,设置标志可能绰绰有余。
答案 2 :(得分:0)
您可以将两个事件都指向一个函数。该功能可以确定发件人并执行适当的操作。