VB.NET 2010 Treeview - vb.net

I have a form with a Treeview control, I add first node pragmatically, when I add the second node the first node gets selected automatically! How to stop that, I dont need any node to be selected unless I select it.
The code i use:
Dim Scr As New TreeNode()
Scr.Text = ObjScreen.ScreenDescription
Scr.Tag = ObjScreen
Scr.SelectedImageIndex = 0
Scr.ImageIndex = 0
tvScreens.Nodes.Add(Scr)

Add this:
Dim Activator as boolean
Private Sub TreeView_BeforeSelect(sender As Object, e As TreeViewCancelEventArgs) Handles TreeView.BeforeSelect
If Activator Then
e.Cancel = True
End if
End Sub
Just set activator to true at the beginning of your code that adds nodes, and false it at the end.

Related

VB.NET - Check if child node if checked in TreeView

I am using Visual Basic .NET 2013 and I want to know which child nodes are checked in a treeview. I don't check parent nodes because the checkboxes are only in child nodes (I have disabled checkboxes in parent nodes, so they don't appear).
At the moment I am using one solution I found:
Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
Dim childNodeCK As TreeNode = e.Node
If childNodeCK.Checked = True Then
If e.Node.Parent Is Nothing = False Then 'detects a Child Node
TextBox1.Text = TextBox1.Text & childNodeCK.Text
MessageBox.Show("Checked: " & childNodeCK.Text)
End If
End If
If childNodeCK.Checked = False Then
If e.Node.Parent Is Nothing = False Then
MessageBox.Show("Unchecked: " & childNodeCK.Text)
End If
End If
End Sub
But I want to know if there is another solution, something like this (the following code doesn't show anything because when I click a button to run it, nothing happens):
For Each childNode As System.Windows.Forms.TreeNode In TreeView1.Nodes
If childNode.Checked = True Then
MessageBox.Show(childNode.Text)
End If
Next
because the idea is to click a button and obtain the name (text) of the child nodes that are checked at that moment. So I think I have to check one by one from the beginning to the end and if the child node is checked then execute some code.
To get all of the checked nodes, you would have to use a recursive function or a stacked list. I prefer the latter:
Private Function GetCheckedNodes() As List(Of TreeNode)
Dim result As New List(Of TreeNode)
'Get the root nodes
Dim nodes As New Stack(Of TreeNode)
For Each tn As TreeNode In TreeView1.Nodes
nodes.Push(tn)
Next
'Check each node and it's children
While nodes.Count > 0
Dim popNode As TreeNode = nodes.Pop
If popNode.Checked Then
result.Add(popNode)
End If
For Each tn As TreeNode In popNode.Nodes
nodes.Push(tn)
Next
End While
Return result
End Function
Then to use it:
For Each tn As TreeNode In GetCheckedNodes()
MessageBox.Show(tn.Text)
Next

Add control in TablelayoutPanel row only

I want to add some control in Tablelayout row 2, but control is just added in Split Container instead and not Tablelayout Itself. TableLayout is inside Split Container. How can I add control only to TableLayoutPanel row 2 ? I use row 1 for different purposes, and I need It visible all the time. Here is my code for adding control to TableLayout :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frm = Me 'Form2 that is currently opened too
If Form1.DataGridView1.Visible = True Then
Form1.DataGridView1.Visible = False
frm.TopLevel = False
Form1.TableLayoutPanel1.Controls.Add(frm, 0, 2)
frm.WindowState = FormWindowState.Maximized
frm.FormBorderStyle = FormBorderStyle.None
frm.Show()
Else 'Do nothing
End If
End Sub
Sorry, too fast on posting. Everything is ok, only problem was "frm.WindowState = FormWindowState.Maximized". I changed It to "frm.Dock = DockStyle.Fill". That solved my issue.

check parent when all its nodes are checked and check all nodes when their parent is checked throws error

I have tried this code:
Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
Dim blnUncheck As Boolean = False
Dim tn As TreeNode
If e.Node.Nodes.Count = 0 Then
For Each child As TreeNode In e.Node.Parent.Nodes
If child.Checked = False Then
blnUncheck = True
End If
Next
If blnUncheck = False Then
e.Node.Parent.Checked = True
Else
e.Node.Parent.Checked = False
End If (the code above is used to check parent when nodes are checked)
Else (the code below is used to check nodes of parent when parent is checked)
If e.Node.Checked = True Then
For Each tn In e.Node.Nodes
tn.Checked = True
Next
Else
For Each tn In e.Node.Nodes
tn.Checked = False
Next
End If
End If
End Sub
in order to: a) check all nodes when their parent is checked
b) check parent when all it's nodes are checked
Although when when I remove one of two(a,b) from the code it works
When I combine them(as the code I have written), it throws a stackoverflow exception.
The code is used in treeview with checkboxes.
EDIT: SOLVED
Visit this linkTreeView.BeforeCheck Event for help (read carefully)
If you try and step through your code you will see that every time you try and check/uncheck a node, you reenter the event.
Try adding this check:
If e.Action = TreeViewAction.Unknown Then
Exit Sub
End If
If you havent manually clicked (EDIT: Also works for selecting by keypress) the node it will exit the event and stop the infinite loop
i think you are looking for that You can try ....
Private Sub CheckAllChildNodes(treeNode As TreeNode, nodeChecked As Boolean)
Dim node As TreeNode
For Each node In treeNode.Nodes
node.Checked = nodeChecked
If node.Nodes.Count > 0 Then
Me.CheckAllChildNodes(node, nodeChecked)
End If
Next node
End Sub
Private Sub node_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
If e.Action <> TreeViewAction.Unknown Then
If e.Node.Nodes.Count > 0 Then
Me.CheckAllChildNodes(e.Node, e.Node.Checked)
Else
e.Node.Parent.Checked = True
End If
End If
End Sub

Dynamically create and remove a control from a form, many times

The below subroutine, when called using a mouse click, successfully creates and then removes a control. but it doesn't create it a second time. I'm assuming it is because the label is not longer dimensioned as public. ie Dim lblDebug1 As New Label is at the top variable section of the form.
However when I put Dim lblDebug1 As New Label in the subroutine the dispose request doesn't work. Is there someway that I can keep creating and disposing a control?
In the below sub, booleanDebug is used to switch back and forth between creating it and disposing it. Thanks in advance.
Dim lblDebug1 As New Label
booleanDebug = Not booleanDebug
If booleanDebug Then
Me.Controls.Add(lblDebug1)
lblDebug1.BackColor = Color.BlueViolet
Else
lblDebug1.Dispose()
End If
Ensure the label has a global context. Within the form that owns it and that you have all the appropriate size and coordinates information and visibility set.
Here is some sample code that worked for me. First just create a new windows form then add a button control in the middle of the form then use the following code.
Public Class Main
Private labelDemo As Windows.Forms.Label
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.SuspendLayout()
If labelDemo Is Nothing Then
labelDemo = New Windows.Forms.Label
labelDemo.Name = "label"
labelDemo.Text = "You Click the Button"
labelDemo.AutoSize = True
labelDemo.Left = 0
labelDemo.Top = 0
labelDemo.BackColor = Drawing.Color.Violet
Me.Controls.Add(labelDemo)
Else
Me.Controls.Remove(labelDemo)
labelDemo = Nothing
End If
Me.ResumeLayout()
End Sub
End Class
Once you've Disposed a control, you can't use it any more. You have two choices here:
Choice 1: Just Remove the control from the form rather than disposing it:
'Top of the file
Dim lblDebug1 As New Label
'Button click
booleanDebug = Not booleanDebug
If booleanDebug Then
lblDebug1.BackColor = Color.BlueViolet
Me.Controls.Add(lblDebug1)
Else
Me.Controls.Remove(lblDebug1)
End If
Choice 2: Create a new control object each time
'Top of the file
Dim lblDebug1 As Label
' ^ No "New".
'We just want an object reference we can share at this point, no need for an instance yet
'Button click
booleanDebug = Not booleanDebug
If booleanDebug Then
lblDebug1 = New Label()
lblDebug1.BackColor = Color.BlueViolet
Me.Controls.Add(lblDebug1)
Else
lblDebug1.Dispose()
End If

Removing a collection of controls

I have a form (Form1) and it has 30 controls.
When I hit a button, I want to remove those 30 buttons and put other controls on the form.
Now, my problem is that this is to slow.
I have this list with controls I want to delete and I run through them with a For Each.
Private Sub ClearControls()
'removing the controls from Me.Controls
For Each Control As Control In ListToDelete
Me.Controls.Remove(Control)
Next
ListToDelete = New List(Of Control)
End Sub
Now, if you watch the form, you see the controls getting deleted 1 by 1. This action takes about 0.4 seconds (timed with the build-in stopwatch) and that's too long.
Are there any solutions to delete the controls in a faster way or is it only possible to delete the controls 1 by 1?
Maybe an important fact is that everything is connected with a database.
The controls are created by a class I defined myself (TableDrawer) and it creates a rectangle or circle (depends on info from the database).
I add the selfmade controls to the form and when I want to delete them, it takes 0.4 seconds to get other controls on the form - also with information out of my database.
Hopefully this clears some things up and I hope you can help me out... It really has to go a bit faster (I hope to get 0.1s or lower)
Hiding the Panel first seems to make the controls disappear quicker than just clearing the Panel. See this code:
Option Strict On
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Panel1.Visible = False
If Not Panel1.Controls.OfType(Of Button).Any() Then
For x As Integer = 1 To 10
For y As Integer = 1 To 10
Dim btn As New Button()
btn.Size = New Size(45, 45)
btn.Location = New Point((x - 1) * 45, (y - 1) * 45)
btn.Text = (x * y).ToString()
Panel1.Controls.Add(btn)
btn.Visible = True
Next
Next
End If
Panel1.Visible = True
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Panel1.Visible = False
Panel1.Controls.Clear()
Panel1.Visible = True
End Sub
End Class
This code has 2 buttons, and a Panel. Button1 generates 100 buttons, places them on a Panel. Button2 hides the panel before removing them. Perhaps you can experiment with this idea.
It's not the deletion that tends to take the time - it's redrawing the form each time. Try surrounding your deletion code with calls to SuspendLayout and ResumeLayout
Private Sub ClearControls()
'removing the controls from Me.Controls
Me.SuspendLayout()
For Each Control As Control In ListToDelete
Me.Controls.Remove(Control)
Next
Me.ResumeLayout()
ListToDelete = New List(Of Control)
End Sub
Put the controls in a panel container control. Removing the panel container removes all child controls.
kindly never used remove and panel.removeat to remove any controls. It won't be able to delete last control in panel layout.Especially for panel.removeat will return out of index error once delete the last end control in panels. I'm also wondering need to know why this is problem appears?
Stored all the control name in string array, find those controls in panel and delete them, Try below code will help you delete all control in panel for one short. Try using with find and removeBykey function will make your task easier.
Dim ctrllist() as string
Dim counts = 0
For each control in Me.panel1.controls
redim Preserve ctrllist(0 to counts)
ctrllist(counts)=control.name
counts+=1
Next
For counts=Lbound(ctrllist) to Ubound(ctrlllist)
If me.panel1.controls.find(ctrllist(counts),True).Length>0 then
me.panel1.controls.removeBykey(ctrllist(counts))
End If
Next
Hope it will help.
Thanks user1884888! The technique helps me.
If I use Me.ScrollPanelControl.Controls.Clear() then the application goes unresponsive and there's no choice to terminate it from Task Manager but using this technique helps me.
This code is to help some one having the same problem.
While (True)
Dim count = Me.ScrollPanelControl.Controls.Count
If count <= 0 Then
Exit While
End If
Dim firstCtrl = CType(Me.ScrollPanelControl.Controls(0), MyControl)
If Not firstCtrl.IsMoving Then
If Me.ScrollPanelControl.Controls.Find(firstCtrl.Name, True).Length > 0 Then
Me.ScrollPanelControl.Controls.RemoveByKey(firstCtrl.Name)
End If
ElseIf count > 1 Then
firstCtrl = CType(Me.ScrollPanelControl.Controls(1), MyControl)
If Me.ScrollPanelControl.Controls.Find(firstCtrl.Name, True).Length > 0 Then
Me.ScrollPanelControl.Controls.RemoveByKey(firstCtrl.Name)
End If
Else
Exit While
End If
End While