开发者

How to deal with sequential calling event handlers?

开发者 https://www.devze.com 2023-03-07 20:19 出处:网络
Before I reinvent the wheel... This is just an EXAMPLE for describing the problem -- let\'s say you have a backend with collection of some data, and frontend which displays one item of the collection

Before I reinvent the wheel...

This is just an EXAMPLE for describing the problem -- let's say you have a backend with collection of some data, and frontend which displays one item of the collection.

At the backend I have ItemIndex -- whenever it changes, it fires up OnScroll event.

I also h开发者_Python百科ave AddNewItem method, it adds new item at the end of the collection. The end of the method is calling OnNewItem event handler.

And here is the catch -- in AddNewItem I have to change ItemIndex, which fires OnScroll. One of the receivers of both (!) OnScroll and OnNewItem if frontend which displays selected item.

In such case it is called twice (not good). One solution would be altering item_index instead of ItemIndex, and this way preventing OnScroll, but I don't like it because ItemIndex does not act as black box anymore.

Is there any established pattern for sequential firing events, and sending only "important" ones (here: OnNewItem overrides OnScroll)? My idea would be to define an event scope, then instead of sending events directly, just register them for sending, and at the close of scope sort them and send the required ones.

In general -- question -- how should I deal with potential sequential event triggering. Use internals to avoid sending redundant events? Ignore the overhead? ...?


The answer seems obvious to me athough I could have easily missed something:

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
   }
}

One thing I would note is that you made mention of just simply altering item_index directly but that wouldn't have a blackbox behavior. Well black box is all well and good ... but that term only applies to objects interacting with this class we have been discussing.

You should feel empowered to use the internals of your class within itself. It is not good OOP to blackbox items within itself. If you are doing that then your class probably has design issues where it should be split into multiple classes.


One solution is to use a 'latch' of some form. When updating, you perform your UI actions via a helper which sets a flag saying 'hey, I'm in a special state!'. Then, when raising events, you check to see if the latch is set -- if it is, you skip raising those events.

It's basically a very simple, generalised version of what Matthew posted. Depending on the situation, setting a flag may be more than adequate.

Jeremy Miller's explanation is worth reading


You could point both events at a single function. The function can determine the sender and perform the appropriate action(s).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号