![](/img/trans.png)
[英]How can I prevent the keydown event of a form in C# from firing more than once?
[英]How can I prevent an event from causing its own event from firing in C#?
我有一個帶有復選框的樹視圖,我有“AfterCheck”事件的以下處理程序:
private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
if (!_isCheckingInProgress)
{
trvAvailableFiles.BeginUpdate();
var nodePath = e.Node.Tag.ToString();
bool isChecked = e.Node.Checked;
e.Node.Nodes.Clear();
try
{
_fileTreeLogic.GetChildNodes(e.Node, true);
e.Node.ExpandAll();
_isCheckingInProgress = true;
SetChildrenCheckState(e.Node, isChecked);
_isCheckingInProgress = false;
}
finally
{
trvAvailableFiles.EndUpdate();
}
}
}
如果仔細觀察,你會發現我正在檢查“_isCheckingInProgress”。 如果不是,那么我繼續並展開所有節點並調用SetChildrenCheckState()方法。 我遇到的問題是SetChildrenCheckState()隨后將導致每個子節點都為其自己的節點觸發AfterCheck事件。
我的問題是,是否有更簡潔的方法允許第一個AfterCheck事件發生而不是后續事件? 我必須有一個實例bool變量來檢查和設置似乎有點hackish。
使用: if(e.Action != TreeViewAction.Unknown)
而不是if (!_isCheckingInProgress)
。 請參見TreeViewAction
。
當用戶使用鍵盤或鼠標檢查復選框時, e.Action
將是TreeViewAction.ByKeyboard
或TreeViewAction.ByMouse
。
MSDN將此作為TreeView.AfterCheck事件的示例代碼提供。
編輯1:顯然,如果您在代碼中自己設置復選框,請將事件處理程序中的代碼移動到新函數,並使用設置復選框的代碼直接調用它。 此解決方案的目的是讓您使用事件處理程序進行用戶輸入,而無需在通過代碼自行設置復選框時觸發這些事件。
編輯2:請參閱斯賓塞的答案,以解釋我在編輯1中的評論
偶爾會看到SO的一個建議是不要將大量代碼放入事件處理程序本身。 有許多的原因。 首先,在您的情況下,更容易理解如下調用:
private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
if (!_isCheckingInProgress)
{
_isCheckingInProgress = true;
try { GetAvailableFiles(); } catch {}
_isCheckingInProgress = false;
}
}
並將其余代碼放在GetAvailableFiles()
。 這在事件代碼和動作代碼之間產生了分離,大多數人都認為這是值得區分的。
其次,在您的情況下可能適用或不適用的是多個事件可能導致相同的操作。 如mnuFileQuit_Click
和btnClose_Click
作為一個明顯的例子。 如果兩者都調用CloseApplication()
它會刪除大量冗余代碼。
就個人而言,我使用一個刪除然后添加事件的函數。
private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
EnableEvents(false);
trvAvailableFiles.BeginUpdate();
var nodePath = e.Node.Tag.ToString();
bool isChecked = e.Node.Checked;
e.Node.Nodes.Clear();
try
{
_fileTreeLogic.GetChildNodes(e.Node, true);
e.Node.ExpandAll();
SetChildrenCheckState(e.Node, isChecked);
}
finally
{
trvAvailableFiles.EndUpdate();
}
EnableEvents(true);
}
private void EnableEvents(bool bEnable)
{
if(bEnable)
cbWhatever.OnChecked += EventHandler;
else
cbWhatever.OnChecked -= EventHandler;
}
不,沒有更清潔的方法來做你所展示的。 我不確定為什么你覺得變量是一種“黑客”方法。 設置標志是編寫UI代碼時常用的技術。
真正的黑客行為將是一種模糊的方式來防止第一次發生事件,但不是隨后的時間。 未來的維護程序員可以保證了解設置標志的工作原理; 他們無法保證欣賞您的替代方法的“優雅”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.