How to create any one dynamic controls with a for loop without using location property and the form should grow automatically - vb.net

How to create multiple button controls with a for loop without getting the controls overlapped and without using location property in Vb.Net.
I have created 'n' number of vb controls dynamically but the created controls are getting overlapped to each other. When I use location property to each controls all the controls are getting displayed as per the location value.
The real problem is, I'm using a panel of width 300 and height 300, under that I need to display the dynamically created controls. I have figured it out which is tedious work and does take a lot of time. My idea is to find the panel width and height then need to check whether the new control which is getting created has ample of space to fit inside the panel.
I need to know few things,
1) How to display the controls dynamically using for loop without getting overlapped over each other and without using location property.
2) I need the container or the panel to grow as per the number of controls which gets created dynamically.
3) Accessing each controls which got displayed using an ID or educate or explain me any better idea.

I created a new WinForms project and added a Button to the top of the form. I added a FlowLayoutPanel under that and made it narrow enough to fit a single Button widthwise. I set the AutoSize property of the FLP to True and the FlowDirection to TopDown. I then added this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create the new Button.
Dim btn As New Button
'Add it to the FLP
FlowLayoutPanel1.Controls.Add(btn)
'Get the position of the bottom, left of the Button relative to the form.
Dim pt = PointToClient(btn.PointToScreen(New Point(0, btn.Height)))
'Resize the form to provide clearance below the new Button.
ClientSize = New Size(ClientSize.Width, pt.Y + 10)
End Sub
I then ran the project and started clicking the Button I added. As expected, each click added a new Button to the FLP in a vertical column and the form resized to fit. In order to access such controls in code, you can simply index the Controls collection of the FLP.

try this helps you.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Do Something
Else
'Do Something else
End If
Panel1.Controls.Clear()
For i As Integer = 0 To 10 Step 1
Dim b15 As New Button
b15.Text = "Test3"
b15.ID = "a" & i
AddHandler b15.Click, AddressOf updateFunc
Panel1.Controls.Add(b15)
Next
End Sub

Related

ListBox past edge of Panel

Here's photo of the form showing the listbox stopping at the edge of the panel when it should extend up past it. I have a project with several panels and a datagridview. I also have some textboxes and buttons. when I click on one of the textboxes, I have a listbox set to be shown and and rezise and locate to just above the textbox but the size I want it to expand to goes beyond the panel and datagrid and that part is not visible.
I've set it to "bring to front" but that doesn't solve the problem
Private Sub txtPayee_Click(sender As Object, e As EventArgs) Handles txtPayee.Click
ListPayee.Show()
ListPayee.BringToFront()
ListPayee.Left = txtPayee.Left
ListPayee.Height = 200
ListPayee.Width = txtPayee.Width
ListPayee.Top = txtPayee.Top - ListPayee.Height
End Sub

How do you set a dynamically created panel to false in VB.net?

I have on my screen design Panel1(left half), and panel2 through 10(right half), the panels on the right half are named based on data from a database.
I need to be able to click on a button in panel1 and when I do so, I need to set visibility to false for the current panel on the right half and set visibility to true that is referenced from the button click. I know that I can do the following but I think this is just way too much overhead and there has to be a better solution than this:
For Each control In Me.Controls.OfType(Of Panel)
If control.visible = true Then
control.visible = false
exit
Next
Panel that the visibility that needs to be set to false was dynamically created so it can not just be accessed by just name, otherwise that would solve my issue easily.
I seen this bit of code elsewhere and it would make my life easier, however not sure how to implement it dynamically when the panels are created, since the name of the panels are unknown at creation.
This bit of code to be able to reference the panels directly.
Dim machinePanel As Panel = DirectCast(Me.Controls.Item("pnl" & strMTB & strMachineID), Panel)
I'm not sure what you mean but "is referenced from the button click", so I'll assume that the text of the button refers to the panel name.
Create a method that handles the visibility
Private Sub SetPanelVisibility(button As Button)
'panel that the button is in
Dim leftPanel = CType(button.Parent, Panel)
'get right panels and ignore left
Dim rightpanels = Me.Controls.OfType(Of Panel).Where(Function(x) x.Name <> leftPanel.Name)
'set visibility of each panel.
For Each panel In rightpanels
panel.Visible = panel.Name = button.Text
Next
End Sub
To call the method just pass the button in on the click event. e.g.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SetPanelVisibility(sender)
End Sub

Refer to a determinate created button

So In my program I’ve putted a flowlayourpanel and with a button I add to the layout infinite new buttons
(button.name = “button” + i.tostring) [i = i + 1]
With another button I want to hide the button with the i=3 so button3.hide(), but it doesn’t work beacause it doesn’t exist yet so How can I refer to the button created when the i was 3?
Name is a property of the Control class so every control has that property. That doesn't mean that it needs to be set though, so some controls don't have a name. When you add a control to your form in the designer, what happens is that the Name property is set AND a field is declared with that name. That's why, if you name a Button control Button1, you are able to use the field Button1 to refer to it.
When you create controls at run time, of course there is no field dedicated to that control so of course you can use such a dedicated field to refer to it. It's up to you to get a reference to that control from wherever you put it when you created it. Where that is is up to you but, if you added it to the Controls collection of a container, that is one option for getting it back. If you set the Name property, you can index the Controls collection with that name to get it, e.g.
Dim myButton = DirectCast(myFlowLayoutPanel.Controls("Button" & i), Button)
There may be other ways of getting that reference too. For instance, if you created your own List(Of Button) and set the Tag of each Button to the number, you could do this:
Dim myButton = myButtonList.Single(Function(btn) CInt(btn.Tag) = i)
When adding your buttons to the FlowLayoutPanel you have correctly assinged a name. You can use this name to refer to the button as shown in Button2.Click.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i = 1 To 5
Dim b As New Button
b.Name = "btn" & i
b.Text = "btn" & i
FlowLayoutPanel1.Controls.Add(b)
Next
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
FlowLayoutPanel1.Controls("btn3").Visible = False
End Sub

Filling a SplitContainer with a TreeView while Dock is set to Fill

If I have a new project with a User Control and a MDI with a 2 window Split Container. One on the left an done on the right. Then If I create a new User Control as follows
Public Class
Private Sub TreeView()
Dim pbTreeView As Forms.TreeView
pbTreeView = New Forms.TreeView()
Me.Controls.Add(pbTreeView)
pbTreeView.Nodes.Clear()
Dim root = New TreeNode("Price Book")
pbTreeView.Nodes.Add(root)
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Settings"))
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Sales"))
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Pricing"))
End Sub
End Class
Private Sub TreeViewControl_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView()
End Sub
I put this User Control in the Left panel of the split container and set the dock to Fill. When I run it. the dock itself is filled properly. but the border and the actual TreeView is NOT made to fit the entirety of the UC in the left container. How can I go about fitting it in there. With the actual data, it will be long enough to even need a horizontal scroll while the data from the selected node will populate the right panel of the spit container(haven't tackled this bit yet).

Darken a .Net Form

I have a 1080p touchscreen application. When a modal pops up, i want to emphasize that by darkening the main form.
Right now i use a second form, the size of the main form, that is black and has 50% opacity. Whenever a modal needs to appear, i open the opaque form, and then open the desired modal.
I feel this is a bit devious for my purpose. Its also not asshole-proof that when the user alt tabs, the forms will glitch out of sequence.
Is there a better way to achieve the darkening effect. Perhaps by darkening the main form from within itself?
Solved it myself by doing the following:
Place a hidden picturebox with dock:fill on the main form,
Take a screenshot of the current screen and darken it
assign the image to the picturebox and make it visible
open the modal in a new win
when the modal is dismissed
hide the picturebox
It really stupid that VB.net doesn't have this function built into it. Here's what you do to get around it:
Make a new form and call it Shade. I'm going to assume your main form is called frmMain. For the sake of clarity, lets assume the form you're launching is called dlgX.
Add the following lines in the Load event of dlgX (that's the sub with dlgX.Load or Me.Load or MyBase.Load):
Shade.Opacity = 0.001
Shade.Show()
Shade.Location = frmMain.Location ' Form location will only update if the form is visible.
Shade.Hide()
Shade.FormBorderStyle = Windows.Forms.FormBorderStyle.None 'This gets rid of the windows Titlebar and window border.
Shade.Size = frmMain.Size
Shade.BackColor = Color.Black
Shade.Opacity = 0.5
Shade.Show() ' Form size will only update the next time you show it.
Shade.TopMost = True ' Puts Shade over main form
Me.TopMost = True ' Puts current form over shade
Under all events that dismiss the form dlgX (OK.click, Cancel.click, etc), add the following lines:
Shade.Close
Or you can even make your own sub that handles all events where the form is closed:
Private Sub DispelShades(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.FormClosed
Shade.Close()
End Sub
This is way simpler than the PictureBox scenario and you don't have to mess with layering issues and having to ensure that the PictureBox renders on top of everything (for example, tabs really do not like having things rendered above them and they will not let you render a picture box above them). Rendering a black semi transparent form above your main form gets around all these headaches.
If you have multiple forms to shade, just make a Shad1, Shade2, Shade3 etc.
This is pretty obvious but it's worth stating: if you're shading the main form, you'll also want to make it unclickable by opening dlgX via dlgX.ShowDialog and not dlgX.Show
Here is some code, very similar to the method in Thomas's answer. Note to use the Darkness property in a Try...Finally block, to make sure you never leave the form in the dark state.
Public Class Form1
Private _PB As PictureBox
Public WriteOnly Property Darkness
Set(value)
If value Then
Dim Bmp = New Bitmap(Bounds.Size.Width, Bounds.Size.Height)
Me.DrawToBitmap(Bmp, New Rectangle(Point.Empty, Bounds.Size))
Using g = Graphics.FromImage(Bmp)
Dim Brush As New SolidBrush(Color.FromArgb(125, Color.Black))
g.FillRectangle(Brush, New Rectangle(Point.Empty, Bmp.Size))
End Using
_PB = New PictureBox
Me.Controls.Add(_PB)
_PB.Size = Bounds.Size
_PB.Location = Bounds.Location - PointToScreen(Point.Empty)
_PB.Image = Bmp
_PB.BringToFront()
Else
If _PB IsNot Nothing Then
Me.Controls.Remove(_PB)
_PB.Dispose()
End If
End If
End Set
End Property
Private Sub btnDialog_Click(sender As Object, e As EventArgs) Handles btnDialog.Click
Try
Darkness = True
MsgBox("Modal dialog")
Finally
Darkness = False
End Try
End Sub
End Class