c# – 区分用户交互引发的事件和我自己的代码

SelectedindexChanged事件从我的应用程序从组合框中触发:

>用户选择不同的
组合框中的项目,或何时:
>我自己的代码更新组合
Box的SelectedItem反映出来
组合框现在正在显示
属性为不同的对象.

我对case1的SelectedindexChanged事件感兴趣,所以我可以更新当前对象的属性.但是在第二种情况下,我不希望事件触发,因为对象的属性没有改变.

一个例子可能有帮助.让我们考虑一下我有一个列表框,其中包含一个人的列表,我有一个组合框,表示当前选定的人在列表中的国籍.如果Fred当前被列入名单,我可以使用案例1,而且我使用组合框将其国籍从英语改为威尔士语.如果我在列表中选择苏格兰的鲍勃,案例2就可能发生.在这里,我的列表更新事件处理程序代码看到Bob现在被选中,并更新组合框,以便苏格兰现在是选定的项目.这导致组合框的SelectedindexChanged事件被触发,以将Bob的国籍设置为苏格兰,即使它已经是苏格兰人.

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

解决方法

我创建了一个我称为SuspendLatch的类.欢迎提供更好的名称,但它可以满足您的需要,您可以使用它:
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时才会使用令牌.尼斯和安全不是线程安全,但…

以下是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);
        }
    }
}

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...