通过用户交互引发的事件和我自己的代码之间的区别 [英] Differentiating between events raised by user interaction and my own code

查看:81
本文介绍了通过用户交互引发的事件和我自己的代码之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的SelectedIndexChanged 事件会得到我的应用程序从一个组合框时触发:

The SelectedIndexChanged event gets fired in my application from a combo box when:


  1. 用户在组合框中选择一个不同的
    项,或当:

  2. 我自己的代码更新组合
    框的的SelectedItem 来反映
    组合框现在已为不同的对象显示
    属性。

  1. the user chooses a different item in the combo box, or when:
  2. my own code updates the combo box's SelectedItem to reflect that the combo box is now displaying properties for a different object.

我感兴趣的是的SelectedIndexChanged 事件情况1,这样我就可以更新当前对象的属性。但是在第二种情况下,我不希望事件,火灾,因为对象的属性没有改变。

I am interested in the SelectedIndexChanged event for case 1, so that I can update the current object's properties. But in case 2, I do not want the event to fire, because the object's properties have not changed.

一个例子可能会有帮助。让我们考虑一下,我有一个包含人的名单列表框,我有代表在列表中的当前选择的人的国籍组合框。如果弗雷德在列表中选择当前可能发生的情形1,我用的是组合框从英语改变自己的国籍威尔士。案例2可能发生,如果我再选择鲍勃,谁是苏格兰人,在列表中。在这里,我的列表更新事件处理程序代码看到鲍勃被选中,并更新组合框以便苏格兰现在是所选项目。这将导致组合框的的SelectedIndexChanged 事件被解雇设置Bob的国籍苏格兰,即使它已经是苏格兰人。

An example may help. Let's consider that I have a list box containing a list of people and I have a combo box representing the nationality of the currently selected person in the list. Case 1 could happen if Fred is currently selected in the list, and I use the combo box to change his nationality from English to Welsh. Case 2 could happen if I then select Bob, who is Scottish, in the list. Here, my list update event-handler code sees that Bob is now selected, and updates the combo box so that Scottish is now the selected item. This causes the combo box's SelectedIndexChanged event to be fired to set Bob's nationality to Scottish, even though it already is Scottish.

如何更新我的组合框的的SelectedItem 属性不会导致在的SelectedIndexChanged 事件触发?一种方法是注销事件处理函数,设置的SelectedItem ,然后重新注册事件处理程序,但这似乎乏味而且容易出错。必须有一个更好的办法。

How can I update my combo box's SelectedItem property without causing the SelectedIndexChanged event to fire? One way would be to unregister the event handler, set SelectedItem, then re-register the event handler, but this seems tedious and error prone. There must be a better way.

推荐答案

我创建了一个类我叫 SuspendLatch 。提供了一个更好的名字是受欢迎的,但它确实你需要什么,你会使用这样的:

I created a class I called SuspendLatch. Offers on a better name are welcome, but it does what you need and you would use it like this:

void Method()
{
    using (suspendLatch.GetToken())
    {
        // Update selected index etc
    }
}

void listbox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (suspendLatch.HasOutstandingTokens)
    {
        return;
    }

    // Do some work
}

这不是很漂亮,但它的工作,而不像注销事件或布尔标志,它支持嵌套操作有点像的TransactionScope。你不断从锁存器取令牌,只有当最后一个令牌配置了 HasOutstandingTokens 返回false它。尼斯和安全。不是线程安全的,但...

It's not pretty, but it does work, and unlike unregistering events or boolean flags, it supports nested operations a bit like TransactionScope. You keep taking tokens from the latch and it's only when the last token is disposed that the HasOutstandingTokens returns false. Nice and safe. Not threadsafe, though...

下面是SuspendLatch代码:

Here's the code for SuspendLatch:

public class SuspendLatch
{
    private IDictionary<Guid, SuspendLatchToken> tokens = new Dictionary<Guid, SuspendLatchToken>();

    public SuspendLatchToken GetToken()
    {
        SuspendLatchToken token = new SuspendLatchToken(this);
        tokens.Add(token.Key, token);
        return token;
    }

    public bool HasOutstandingTokens
    {
        get { return tokens.Count > 0; }
    }

    public void CancelToken(SuspendLatchToken token)
    {
        tokens.Remove(token.Key);
    }

    public class SuspendLatchToken : IDisposable
    {
        private bool disposed = false;
        private Guid key = Guid.NewGuid();
        private SuspendLatch parent;

        internal SuspendLatchToken(SuspendLatch parent)
        {
            this.parent = parent;
        }

        public Guid Key
        {
            get { return this.key; }
        }

        public override bool Equals(object obj)
        {
            SuspendLatchToken other = obj as SuspendLatchToken;

            if (other != null)
            {
                return Key.Equals(other.Key);
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return Key.GetHashCode();
        }

        public override string ToString()
        {
            return Key.ToString();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Dispose managed resources.
                    parent.CancelToken(this);
                }

                // There are no unmanaged resources to release, but
                // if we add them, they need to be released here.
            }
            disposed = true;

            // If it is available, make the call to the
            // base class's Dispose(Boolean) method
            //base.Dispose(disposing);
        }
    }
}

这篇关于通过用户交互引发的事件和我自己的代码之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆