2011-05-25 83 views
13

所以我有一個C#窗體窗體應用程序中的TreeView。我需要的是一些節點被「鎖定」,以便它們不能根據參數進行檢查(或未選中)。C#:如何避免雙擊事件發生TreeNode檢查

我現在正在做的是這樣的:

private void tv_local_BeforeCheck(object sender, TreeViewCancelEventArgs e) { 
    TNode node = (TNode)e.Node; 
    //if a part node, cancel the action. 
    if (node.Type == "Part") { 
     e.Cancel = true;  
    } 
    //if a locked node, cancel the action 
    if (node.Locked == true) { 
     e.Cancel = true; 
    } 
} 

該代碼中的複選框的單次點擊的偉大工程,但如果一個複選框用戶雙擊,它仍然會檢查/取消選中。

我曾嘗試與nodeMouseDoubleClick事件打,但並沒有真正的幫助,因爲我無法取消的事件......

有任何想法在那裏如何取消節點上的雙擊事件? ..還是其他什麼? 謝謝

+0

你能後的您的DoubleClick活動處理程序的代碼? – 2011-05-25 20:24:52

+0

我沒有寫在那裏的東西。我不希望任何事情發生在雙擊... 如果我可以做e.Cancel = true,那將是doubleclick事件中的代碼 – Toadums 2011-05-25 20:25:53

+0

您確定沒有任何其他處理程序被設置嗎?我剛剛嘗試將樹形視圖拖放到窗體上,但無法重現問題(我正在使用VSTS2008) – 2011-05-25 20:37:16

回答

21

這是我認爲TreeView中的一個錯誤(http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/9d717ce0-ec6b-4758-a357-6bb55591f956/)。您需要繼承樹視圖的子類並禁用雙擊消息才能修復它。就像這樣:

public class NoClickTree : TreeView 
    { 
     protected override void WndProc(ref Message m) 
     { 
      // Suppress WM_LBUTTONDBLCLK 
      if (m.Msg == 0x203) { m.Result = IntPtr.Zero; } 
      else base.WndProc(ref m); 
     }    
    }; 

當然,如果你這樣做,你將不再能夠使用在樹視圖其他的東西(如雙雙擊比喻單擊一個節點發動屬性頁, 或者其他的東西)。

+0

我曾經見過這個解決方案,但無法弄清楚如何使它工作 - 我沒有意識到,我不得不創建一個新類並擴展treeview類。謝謝!! – Toadums 2011-05-25 20:43:32

+1

請記住,您必須在'Form1.Designer.cs'文件中將您的樹視圖初始化爲'NoClickTree',而不是'Form1.cs',如[在此解釋](http://stackoverflow.com/a/14758596/1677209) – T30 2014-08-04 15:22:53

+0

不錯!這個bug一直是頭疼! (至少對我來說) – 2014-09-11 05:37:47

0

嘗試擴展TreeNode類並添加一個布爾屬性來維護正確的checkedState。這樣,當某人雙擊某個節點時,可以將該節點的選中狀態重置爲存儲在該屬性中的值。可能有更優雅的解決方案,但這是我能想到的最好的。

1

我用下面的代碼,以防止檢查根節點管理它:

private void MyTreeView_MouseUp(object sender, MouseEventArgs e) 
{ 
    // HACK: avoid to check root nodes (mr) 
    var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y)); 
    if (node != null && node.Parent == null) 
    BeginInvoke(new MouseEventHandler(TreeView_MouseUpAsync), sender, e); 
} 

private void TreeView_MouseUpAsync(object sender, MouseEventArgs e) 
{ 
    if (IsDisposed) 
     return; 

    var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y)); 
    node.Checked = false; 
} 
4

如果你希望你雙擊實際切換複選框,然後嘗試:

protected override void WndProc(ref Message m) 
{ 
    // Filter WM_LBUTTONDBLCLK when we're showing check boxes 
    if (m.Msg == 0x203 && CheckBoxes) 
    { 
    // See if we're over the checkbox. If so then we'll handle the toggling of it ourselves. 
    int x = m.LParam.ToInt32() & 0xffff; 
    int y = (m.LParam.ToInt32() >> 16) & 0xffff; 
    TreeViewHitTestInfo hitTestInfo = HitTest(x, y); 

    if (hitTestInfo.Node != null && hitTestInfo.Location == TreeViewHitTestLocations.StateImage) 
    { 
     OnBeforeCheck(new TreeViewCancelEventArgs(hitTestInfo.Node, false, TreeViewAction.ByMouse)); 
     hitTestInfo.Node.Checked = !hitTestInfo.Node.Checked; 
     OnAfterCheck(new TreeViewEventArgs(hitTestInfo.Node, TreeViewAction.ByMouse)); 
     m.Result = IntPtr.Zero; 
     return; 
    } 
    } 

    base.WndProc(ref m); 
} 
+0

我用你的代碼,它似乎工作。非常感謝。 – DonkeyMaster 2013-07-19 13:10:05

+0

完美的作品! – 2016-08-02 11:55:44