I created several user controls that i want to display on a main panel.
Thus, I have this function that takes in input the control I want to display by setting it to visible, and visible = false for all other ones :
Public Sub ShowControl(ByVal Controle As Control)
MainPanel.BringToFront()
Try
With MainPanel
For Each contr As Control In .Controls
If contr.Name <> Controle.Name Then
contr.Visible = False
Else
' Display the control
contr.Visible = True
End If
Next
End With
Catch ex As Exception
End Try
It works well when my panel has different user controls like this :
Public WithEvents uc1 As New User_Control1
Public WithEvents uc2 As New User_Control2
Public WithEvents uc3 As New User_Control3
MainPanel.Controls.Add(uc1)
MainPanel.Controls.Add(uc2)
MainPanel.Controls.Add(uc3)
But not if I create several instances from the same user control :
Public WithEvents uc1 As New User_Control1
Public WithEvents uc2 As New User_Control1
Public WithEvents uc3 As New User_Control1
MainPanel.Controls.Add(uc1)
MainPanel.Controls.Add(uc2)
MainPanel.Controls.Add(uc3)
I know that this is because in my function the name Controle.name will remain the same (User_Control1), but is there any way to make it works ?
Related
I have a user control that contains 2 panels. Panel1 is the parent for Panel2 so Panel2 is placed inside the Panel1 container. Now, at runtime, I want to add controls to my user control. These new controls must be placed inside Panel2. Addings controls with myUserControl.Controls.Add would normally put the new controls into the user control itself and not inside Panel2. I would like Panel2 to be the default container for all controls that are added to the user control at runtime. How to do this?
You can override OnControlAdded, verify whether the UC Handle is already created (InitiaizeComponent() has already being executed, so all child Controls added in the Designer have already been added to the UC's Controls collection), then add the new Control to Panel2.Controls collection:
Public Class MyUSerControl
Inherits UserControl
Protected Overrides Sub OnControlAdded(e As ControlEventArgs)
If IsHandleCreated AndAlso e.Control IsNot Panel1 Then
Panel2.Controls.Add(e.Control)
End If
MyBase.OnControlAdded(e)
End Sub
End Class
Or, you could add a public method that performs this action:
Dim btn1 = New Button() With {.Text = "Button1", .Name = "Button1"}
Dim btn2 = New Button() With {.Text = "Button2", .Name = "Button2"}
myUSerControl.AddControls(btn1)
' Or
myUSerControl.AddControls({btn1, btn2})
Public Class MyUSerControl
Inherits UserControl
Public Sub AddControls(ParamArray newControls As Control())
Panel2.Controls.AddRange(newControls)
End Sub
End Class
I have a panel and a button in a form and 2 user controls, I dynamically loaded the first user control in the panel then inside the userControl1 I have a method that I want to access when I clicked the button in the form and then change the displayed user control to userControl2 in the panel, how should I do that?
form1 code:
Public Class form1
Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim control1 = New UserControl1
Panel1.Controls.Add(control1)
control1.Location = New Point(0, 0)
control1.Size = New Point(1351, 533)
End Sub
End Class
UserControl1 Code:
Public Class UserControl1
Public Sub doSomething()
'Do something'
End Sub
End Class
OK, I'll take as much as I can from your question and show you an example, there are many different ways you could do this, thus, may not answer your question 100% but will give you enough to get what you want.
I'm making an assumption that you only have one control1 and one control2.
My example will alternate, and access a sub routine in the active (shown) usercontrol on each click on the main form button.
In a module I would put:
Public control1 As New UserControl1
Public control2 As New UserControl2
In UserControl1 put:
Public Sub DoSomething()
Me.BackColor = Color.Black
End Sub
In UserControl2 put:
Public Sub DoSomething()
Me.BackColor = Color.White
End Sub
In your FormLoad event put:
control1.Location = New Point(0, 0)
control1.Size = New Point(1351, 533)
Panel1.Controls.Add(control1)
In your Button1 click event put:
Select Case Panel1.Contains(control1)
Case True
'Remove UserControl1 - Add UserControl2
Panel1.Controls.Remove(control1)
control2.Location = New Point(0, 0)
control2.Size = New Point(1351, 533)
Panel1.Controls.Add(control2)
control2.DoSomething()
Case False
'Remove UserControl2 - Add UserControl1
Panel1.Controls.Remove(control2)
control1.Location = New Point(0, 0)
control1.Size = New Point(1351, 533)
Panel1.Controls.Add(control1)
control1.DoSomething()
End Select
The above is checking which UserControl is in the panel and alternating it and calling the 'DoSomething'. This is just an example to give you an idea. What you want may be different, you may have a button in your second UserControl and if so, amend the switch code to suit.
Private Sub tsGradovi_Click(sender As Object, e As EventArgs) Handles tsGradovi.Click
For Each f As Form In Application.OpenForms
If TypeOf f Is frmGradovi Then
f.Activate()
Return
End If
Next
Dim f2 As New frmGradovi
f2.MdiParent = Me
f2.Show()
f2.WindowState = FormWindowState.Maximized
resetdgvGradova()
End Sub
On this way i add the Child form to my main Form.
On that frmGradovi form i have the datagridview. Now i added class to my project.
How can i add the datagridview source from my class.
this code is not helping
frmGradovi.DGV.DataSource = SQLDataset.Tables(0)
Probabbly because frmGradovi is mdi child of form1.
Edit:
At class konekcija i need to set the datasource for the frmGradovi form. But that frmGradovi form is an mdi child form of Form1
One way to avoid these types of conundrums is not to write Form-centric code. They are basically a sandbox for collection user input. The other element is to explicitly instance forms: In your code f2 is an instance of frmGradovi. Trying to reference it as frmGradovi elsewhere risks creating a new default instance of it (you'd later have 2 forms of Type frmGradovi in your Forms collection).
I dont know what a Gradovi or a konekcija is, so I will use a Customer example. My app might have a frmCustomer and a Customer class. When it comes time to display a certain customer, rather than the MDI parent form code or button click creating the form, I'd leave that job to the Customer class:
Public Class Customer
' myFrm is an instance of frmCustomer, which is a Type
Private myFrm As frmCustomer
Private myDT As DataTable
Public Sub Display(Id As Int32)
CustId = Id
If myFrm Is Nothing Then
myFrm = New frmCustomer
' MDI boilerplate code
'...
' one time setup code like populate static CBOs:
'...
End If
UpdateDisplay()
myFrm.BringToFront()
End Sub
Public Sub UpdateDisplay()
' display code when something changes such as show new selected Customer
' e.g.:
LoadCustDataToDataTable(CustId)
With myFrm
.tbfirstName.Text = FirstName
.tbLastName.Text = LastName
' ...etc
.dgvPastOrders.DataSource = myDT
End With
End Sub
The "key" is that the Customer class is in charge of the customer form. It creates it and retains a reference to it. When the user clicks Save that task too would be offloaded to the Customer.Save method.
You'll have other gyrations to add to handle when the user closes that form (if they are allowed to close versus just hiding it). In your current approach, your class could fish the reference to its form from the collection as it needs it.
i am trying to access data from textboxes and checkboxes placed on form1 in a task running on form2.
When i access the textboxes and checkboxes within a task started in a sub of form1 everything works fine!
But if i try to use the data from the controls in a task of form2 i only get the default text (empty) of the textbox and the default checked status
The following testsub works on form1 and the right text is shown.
Public Sub testsub()
Dim testTask As New Task(Sub() MsgBox(TextBox1.Text))
testTask.Start()
End Sub
On form2 i tried this
Public Sub testsub()
Dim testTask As New Task(Sub() MsgBox(Form1.TextBox1.Text))
testTask.Start()
End Sub
This doesn't work and only an empty textbox is shown.
It seems that the standard instance of the form1 is not available in the task of form2?! Is that right?
So how can i access the control data of form1 in the task of form2?
You need your instance of Form1 declared in a place Form2 can access it.
Try adding a module :
Module Mod1
Public f1 as Form1
End Module
Then in the Form1 Load event, set f1 to the instance of Form1
f1 = Me
After Form1 has been loaded, then in Form2 you can use your sub, replacing the general Form1 with the specific f1
Public Sub testsub()
Dim testTask As New Task(Sub() MsgBox(f1.TextBox1.Text))
testTask.Start()
End Sub
I have two forms, form 1 and form 2 (windows application). How can i access and check a checkbox in form 1 from form 2. Initially i tried calling the form name and then the control like form1.chkCanada.checked = true, it did not work. And then i added a property in form 1
Public Property abc As Boolean
Get
Return chkCanadianStmtInd.Checked
End Get
Set(value As Boolean)
chkCanadianStmtInd.Checked = value
End Set
End Property
and then in form 2
Dim frm As New frm1
frm.abc = True 'Checked
And it still doesnt work. Am i missing anything here?
Alternatively you can pass a handle of form1 to form2 constructor
Form1:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim _form2 As New Form2(Me)
_form2.Show()
End Sub
End Class
Form2:
Public Class Form2
Public Sub New(ByVal _form1 As Form1)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_form1.CheckBox1.Checked = True
End Sub
End Class
Consolidating comments here:
In order to access controls on a form that shows another form to the user you have two options, if no interaction is needed with the first form while the second form is active you can use showdialog and do all of your logic after the second form has closed, if you ned to maintain the ability to interact with the first form while the second is still open then you need to use custom events.
Showdialog:
The simpler of the two options is to switch your form.show() function calls to form.showdialog(). This effectively tells the first form that it should stop processing at the form.showdialog() line and wait for the child form to close before proceeding. Once the second form is closed the first form will pick up where it left off and that would be where any processing that relies on the values of the second form would take place.
Custom Events:
If you want to allow the user to interact with both the first and second forms at the same time then you will need to use custom events. In order to do this you will need three things. The custom event, a raiseevent call and an event handler.
So in your Form2 class you will need to declare the custom event. In this case since you are trying to check(or uncheck I assume) a box your custom event declaration will look like:
public event ChangeCheckedValue(byref state as boolean)
Now on your button click event you will need to raise the event to the handler on Form1:
RaiseEvent ChangeCheckedValue(booleanValue)
Now that those statements are in place you will need to changed your form2 object that is being shown by Form1. What I normally do is make Form2 a form wide variable on Form1 and declare it like:
private withevents frm as Form2
Once you have the frm variable in your Form1 class you can add a handler for the ChangeCheckedValue event:
protected sub HandleCheckChanged(byref bln as boolean) handles frm.ChangeCheckedValue
'Set the checked state of your checkbox.
End sub
Once you have all that set up you should see what you expect.