2009-12-31 96 views
0

我是使用樹視圖的新手,我希望能夠確保樹視圖只能檢查一個子節點,並且如果有人試圖檢查多個然後停止檢查事件並取消選擇所有父節點和子節點。我會如何去做這件事?到目前爲止,這是我得到的,但它的表現古怪。有什麼建議麼?檢查TreeView中檢查的節點數

更新:爲了澄清一些事情,這是一個雙贏的形式treeview和父節點是一個類別,每個類別可以包含多個項目。我只希望用戶能夠一次從類別中選擇一個類別和一個項目。

private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) 
{ 
    int checkedNodeCount = 0; 

    if (e.Node.Parent != null && !e.Node.Parent.Checked) 
     e.Cancel = true; 
    else 
    { 
     foreach (TreeNode node in tvRecipes.Nodes) 
     { 
      if (node.Checked) 
       ++checkedNodeCount; 

      if (checkedNodeCount > 2) 
      { 
       MessageBox.Show("Only one recipe can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 

       e.Cancel = true; 
      } 
     } 
    } 

經過一番混亂之後,我想出了我之後的解決方案。我已在下面發佈它:

private bool CheckNumOfSelectedChildern(TreeViewEventArgs e) 
{ 
    bool Valid = true; 
    int selectedChildern = 0; 

    foreach (TreeNode node in tvRecipes.Nodes) 
    { 
     if (node.Checked) 
     { 
      foreach (TreeNode child in node.Nodes) 
      { 
       if (child.Checked) 
        ++selectedChildern; 
      } 
     } 
    } 

    if (selectedChildern > 1) 
    { 
     MessageBox.Show("Only one recipe per category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     e.Node.Checked = false; 
     e.Node.Parent.Checked = false; 
     Valid = false; 
    }  
    return Valid; 
} 

private bool CheckNumOfSelectedParents(TreeViewEventArgs e) 
{ 
    bool Valid = true; 
    int selectedParent = 0; 

    foreach (TreeNode root in tvRecipes.Nodes) 
    { 
     if (root.Checked) 
      ++selectedParent; 
    } 

    if (selectedParent > 1) 
    { 
     MessageBox.Show("Only one recipe category can be selected at a time, please deselect the current recipe and try again.", "Too Many Recipes Selected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     e.Node.Checked = false; 
     Valid = false; 
    } 
    return Valid; 
} 

private void tvRecipes_BeforeCheck(object sender, TreeViewCancelEventArgs e) 
{ 
    if (e.Node.Parent != null && !e.Node.Parent.Checked) 
     e.Cancel = true; 
    else if (e.Node.Checked) 
    { 
     foreach (TreeNode child in e.Node.Nodes) 
     { 
      if (child.Checked) 
       e.Cancel = true; 
     } 
    } 
} 

private void tvRecipes_AfterCheck(object sender, TreeViewEventArgs e) 
{ 
    if (CheckNumOfSelectedParents(e)) 
    { 
     if (e.Node.Parent != null && e.Node.Parent.Checked) 
     { 
      if (e.Node.Checked) 
      { 
       if (CheckNumOfSelectedChildern(e)) 
       { 
        RecipeDs = RetrieveRecipe.FillRecipeDs(e.Node.Text); 
        DataBindControls(); 
       }      
      } 
      else 
      { 
       RemoveLabelsFromLayout(); 
       RemoveDataBindings(); 
       RecipeDs.Clear(); 
       this.Refresh(); 
      } 
     } 
    } 
} 
+0

@Nathan,嗨,我看你接受了我的答案只能選擇一個節點,其對於你的問題來說,這是一個長期的「評論」。我不確定我的「長評論」是否構成「答案」值得接受,所以請,如果您得到「更好的答案」,請毫不猶豫地選擇它。再次,我可以(溫和地)鼓勵你澄清一下你的問題。最好, – BillW 2009-12-31 04:05:35

+0

@Nathan,有幾個問題:1.通過設計,最終用戶無法檢查或取消選中類別節點? 2.如果用戶可以檢查一個類別(根)節點:但是不在檢查的類別節點中選擇一個項目(子節點):這是一個錯誤條件嗎? 3.只有檢查一個子節點的行爲纔會自動檢查你剛檢查過的子節點的父節點的根節點。 4.如果允許取消選中某個類別節點,並且在其父節點(類別)節點內選中了一個節點節點,那麼當我取消選中該節點ndoe時:類別節點(父節點)也必須取消選中? – BillW 2010-01-01 03:28:04

+0

@Nathan,嗨,一旦我們確切地知道類別節點(無父節點,根節點)能做什麼和不能做什麼,這種情況可以很容易地用一個或兩個布爾標誌來管理,或者也許只有使用兩個對當前檢查的類別節點(無父母,根)和當前檢查的項目節點(子節點)的引用。最好的, – BillW 2010-01-01 03:48:04

回答

1

這太長了只是一個評論。

我假設你正在描述標準的Windows窗體TreeView:正確嗎?

當你在你的問題說:

如果有人試圖查看更多然後 一個停止檢查事件和 取消選擇所有父和子節點。

對我來說,意味着你必須能夠多選的樹視圖,以及標準的Windows窗體TreeView是這個能力。你可以「破解它」,因此它可以進行多選:例如:CodeProject : "Multiselect Treeview Implementation",但這樣做並不重要。

所以我會假設你的意思是「取消」父和子節點:但後來:這是令人困惑,因爲你的問題似乎問清楚你如何只生一個孩子的TreeNode檢查一次:暗示對我來說,你將不得不「取消」任何其他子節點。

讀取您的代碼,顯然您計劃檢查一個父節點的可能性,但您並未明確排除可以檢查多個「無父母」(根)節點的情況。

所以,建議重新說明你的問題稍微清楚闡明:

  1. 不是一個無父無母(根)節點更可以檢查?

  2. 一次只能檢查一個父母(根)節點嗎?

  3. 檢查每個無父節點(根)節點時,可以在任何時候檢查一個且只有一個子節點?

  4. 如果子節點是「深層嵌套」的:這對你有什麼影響嗎?

注意:由於原生WinForms TreeView控件的很大侷限性,我們很多人都購買了第三個。第三方TreeView控件:

我購買了Integral UI TreeView from Lidor Systems,並一直很高興。 Lidor TreeView的內置屬性是包含所有當前檢查節點的CheckedNodes集合,並且您可以選擇三種選擇模式,包括一個「MultiExtended」,它允許您在其中包含子節點和父節點的非常複雜的選擇任何順序,在任何級別的「嵌套」:

當然,你有一個'任何時候可用的SelectedNodes集合包含所有選定的節點。

利用Lidor TreeView,您可以隨時(在設計時或運行時)隱藏任何一個節點的複選框,並且CheckBox支持三種狀態:「不確定」以及「已選中」和「未選中」。

我假設其他3。第三方TreeView控件也提供了類似的功能,但是當我在兩年前審查並嘗試了大部分主要功能的「試用版本」時:對於我來說,Lidor TreeView提供了最大的價值並且並不昂貴。在豐富「風格」TreeNodes的能力方面,我沒有看到任何與「WinForms Universe」中的Lidor TreeView功能接近的東西。披露:我不爲Lidor工作,並且與他們沒有業務關係:我只是一個滿意的推薦顧客。

1

你的if(checkedNodeCount> 2)...應該在foreach循環之外。

在for循環中,它每次都會運行。我假設這是你的意思是「行爲古怪」

也許你應該提供一些關於不正確行爲的更多細節。

1

希望這個作品:

private int _callCountUp; 

     private int _callCountDn; 

private void tvwPermissions_AfterCheck(object sender, System.Windows.Forms.TreeViewEventArgs e) 
     { 
      bool anyChecked = false; 

      if (_callCountDn == 0 && e.Node.Parent != null) 
      { 
       anyChecked = false; 
       foreach (TreeNode childNode in e.Node.Parent.Nodes) 
       { 
        if (childNode.Checked) 
        { 
         anyChecked = true; 
         break; 
        } 
       } 
       _callCountUp += 1; 

       if (anyChecked) 
        e.Node.Parent.Checked = true; 

       _callCountUp -= 1; 
      } 

      if (_callCountUp == 0) 
      { 
       foreach (TreeNode childNode in e.Node.Nodes) 
       { 
        _callCountDn += 1; 
        childNode.Checked = e.Node.Checked; 
        _callCountDn -= 1; 
       } 
      } 
     } 
0

有人問一年前,但there是尖端,如何在樹形