在以下情况SelectedIndexChanged下,从组合框中在我的应用程序中触发该事件:
SelectedItem以反映组合框现在显示不同对象的属性.我SelectedIndexChanged对案例1 的事件感兴趣,以便我可以更新当前对象的属性.但在案例2中,我不希望事件触发,因为对象的属性没有改变.
一个例子可能有帮助.让我们考虑一下,我有一个包含人员列表的列表框,我有一个组合框,表示列表中当前所选人员的国籍.如果当前在列表中选择了Fred,则可能发生情况1,并且我使用组合框将他的国籍从英语更改为威尔士语.如果我在列表中选择苏格兰人Bob,则可能发生案例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
}
Run Code Online (Sandbox Code Playgroud)
它不漂亮,但确实有效,与注销事件或布尔标志不同,它支持嵌套操作,有点像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);
}
}
}
Run Code Online (Sandbox Code Playgroud)