Předpokládám, že pracujete s Windows Forms a ne s WPF? Jestli tomu správně rozumím, máte nějakou stromovou strukturu CheckBoxů, kdy při zaškrtnutí rodiče chcete zaškrtnout také všechny potomky. Může to vypadat třeba takhle:
× CheckBox1 × CheckBox2 × CheckBox3
× CheckBox1.1 × CheckBox2.1 × CheckBox3.1
× CheckBox1.2 × CheckBox2.2 × CheckBox3.1.1
× CheckBox1.3 × CheckBox3.1.2
× CheckBox3.2
Napadá mě například takové řešení, kdy všechny dceřinné CheckBoxy dáte do kontejneru typu Panel, či GroupBox a při zaškrtnutí rodičovského CheckBoxu budete iterovat kolekcí CheckBoxů v asociovaném GroupBoxu (Panelu, ...). V příkladě výše tedy budou v jednom GroupBoxu CheckBoxy 1.1, 1.2 a 1.3, v druhém 2.1 a 2.2 a ve třetím budou dva CheckBoxy 3.1 a 3.2 a další GroupBox (který ale nebude součástí iterované množiny), který bude asociovaný s 3.1. Hromadné zaškrtnutí všech CheckBoxů pak bude vypadat takto:
Private Sub Zaskrtej(checkBox As CheckBox, groupBox As GroupBox, checked As Boolean)
For Each checkBox In groupBox.Controls.OfType(Of CheckBox)
checkBox.Checked = checked
Next
End Sub
Tuto metodu zavoláte na každém CheckBoxu, který má asociovaný nějaký GroupBox.
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
Dim checkBox = DirectCast(sender, CheckBox)
Zaskrtej(checkBox, GroupBox1, checkBox.Checked)
End Sub
Alternativně (pokud je CheckBoxů mnoho) můžete také použít místo handlerů zaškrtnutí jednotlivých CheckBoxů (Sub CheckBoxX_CheckChanged) toto v události Load formuláře:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
' Definujeme asociace mezi CheckBoxy a GroupBoxy
Dim associations = New Dictionary(Of CheckBox, GroupBox)
associations.Add(CheckBox1, GroupBox1)
associations.Add(CheckBox2, GroupBox2)
associations.Add(CheckBox3, GroupBox3)
associations.Add(CheckBox9, GroupBox4)
Dim checkBoxStack = New Stack(Of CheckBox)
Controls.OfType(Of CheckBox).ToList().ForEach(Sub(cb) checkBoxStack.Push(cb))
' Rekurzivně projíždíme všechny CheckBoxy na formuláři, které mají definovanou asociaci
While checkBoxStack.Peek() IsNot Nothing
Dim checkBox = checkBoxStack.Pop()
If associations.ContainsKey(checkBox) Then
' Přidáme handler při zaškrtnutí CheckBoxu
AddHandler checkBox.CheckedChanged,
Sub(sender2, e2)
Dim checkBox2 = DirectCast(sender2, CheckBox)
Zaskrtej(checkBox2, associations(checkBox2), checkBox2.Checked)
End Sub
' Přidáme na Stack další CheckBoxy v GroupBoxu
associations(checkBox).Controls.OfType(Of CheckBox).ToList().ForEach(Sub(cb) checkBoxStack.Push(cb))
End If
End While
End Sub
Pokud netrváte vyloženě na použití CheckBoxů a jde Vám spíše o funkcionalitu, pro mnoho voleb by možná bylo lepší použít TreeView, kterému nastavíte vlastnost CheckBoxes na True a tím pádem přidáte ke všem položkám zaškrtávací pole. Pak už stačí jen:
Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
' Ujistíme se, že událost vyvolal uživatel
If e.Action.HasFlag(TreeViewAction.ByKeyboard) OrElse e.Action.HasFlag(TreeViewAction.ByMouse) Then
' True pokud zaškrtnout všechny potomky
' False pokud zaškrtnout pouze potomky první úrovně
Zaskrtej2(e.Node, e.Node.Checked, False)
End If
End Sub
Private Sub Zaskrtej2(node As TreeNode, checked As Boolean, recursive As Boolean)
For Each childNode As TreeNode In node.Nodes
childNode.Checked = checked
'If recursive Then Zaskrtej2(childNode, checked, True)
Next
End Sub
|