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

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

问题描述

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.

我对案例 1 的 SelectedIndexChanged 事件感兴趣,以便我可以更新当前对象的属性.但在情况 2 中,我不希望事件触发,因为对象的属性没有改变.

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.

一个例子可能会有所帮助.让我们考虑一下,我有一个包含人员列表的列表框,我有一个表示列表中当前选定人员的国籍的组合框.如果 Fred 当前在列表中被选中,则可能发生情况 1,并且我使用组合框将他的国籍从英语更改为威尔士语.如果我在列表中选择苏格兰人 Bob,则可能会发生情况 2.在这里,我的列表更新事件处理程序代码看到 Bob 现在被选中,并更新组合框,以便 Scottish 现在是选中的项目.这会导致组合框的 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.

如何在不触发 SelectedIndexChanged 事件的情况下更新组合框的 SelectedItem 属性? 一种方法是取消注册事件处理程序, 设置 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天全站免登陆