VB.NET UserControl does not receive parent form's events - vb.net

I have created a usercontrol and added it to a form.
I would like to receive the form's event using Private WithEvents _Parent As Form.
But none of the events is being received.
The entire code of my usercontrol is attached.
Does anybody see what I am doing wrong?
Public Class UserControl1
Private WithEvents _Parent As Form
Public Sub New()
InitializeComponent()
_Parent = Me.Parent
End Sub
Private Sub _Parent_Activated(sender As Object, e As EventArgs) Handles _Parent.Activated
MsgBox("activated")
End Sub
Private Sub _Parent_Resize(sender As Object, e As EventArgs) Handles _Parent.Resize
MsgBox("resize")
End Sub
End Class

When the constructor is called, there is no parent yet (Windows Forms controls are added to their parents after the class is created). Me.Parent returns Nothing at this point.
Handle Me.ParentChanged to initialize _Parent:
Private Sub UserControl1_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ParentChanged
_Parent = Me.Parent
End Sub

Related

How to check if a Form has focus?

I have two WinForms. Let's say MainForm and ChildForm.
What I'm trying to make is when the MainForm is activated the ChildForm should always be visible, and when the MainForm loses focus the ChildForm should be hidden except if it's the ChildForm which was activated.
Here is my code :
AddHandler Me.MainForm.Activated, Sub()
Me.ChildForm.Show()
End Sub
AddHandler Me.MainForm.Deactivate, Sub()
If Not Me.ChildForm.Focused Then
Me.ChildForm.Hide()
End If
End Sub
AddHandler Me.ChildForm.Deactivate, Sub()
If Not MainForm.Focused Then
Me.ChildForm.Hide()
End If
End Sub
The code doesn't work. Basically when I click on a certain form (on the child form for example), the property Me.ChildForm.Focused is not correct and then ChildForm is hidden while it should be visible.
Can anyone know how to achieve that please ?
Not sure if this is a good one, but the idea is using flags for MainForm and ChildForm active status. These flags are set when MainForm and ChildForm's Activated and Deactive events are fired. For simplicity, I'll use a module to store the flags and the instance of ChildForm. Then call SetChildVisible() method in MainForm, Form1 and Form2 Activated event. Set startup object to MainForm.
Module1
Module Module1
Public FChild As ChildForm
Public FMainActive As Boolean
Public FChildActive As Boolean
Public Sub SetChildVisible()
FChild.Visible = Not FChildActive And FMainActive
End Sub
End Module
MainForm
Public Class MainForm
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim f1 = New Form1
Dim f2 = New Form2
Dim child = New ChildForm
Module1.FChild = child
child.Show()
f1.Show()
f2.Show()
End Sub
Private Sub MainForm_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
Module1.FMainActive = True
Module1.SetChildVisible()
End Sub
Private Sub MainForm_Deactivate(sender As Object, e As EventArgs) Handles MyBase.Deactivate
Module1.FMainActive = False
End Sub
End Class
ChildForm
Public Class ChildForm
Private Sub ChildForm_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
Module1.FChildActive = True
End Sub
Private Sub ChildForm_Deactivate(sender As Object, e As EventArgs) Handles MyBase.Deactivate
Module1.FChildActive = False
End Sub
End Class
Form1
Public Class Form1
Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
Module1.SetChildVisible()
End Sub
End Class
Form2
Public Class Form2
Private Sub Form2_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
Module1.SetChildVisible()
End Sub
End Class

Force Custom Event Handler First

When I create custom handlers like:
Public Class MyCustomClass
Public Sub AddHandlers()
AddHandler Form1.MouseMove, AddressOf MoveMouse
End Sub
Private Sub MoveMouse(sender As Object, e As MouseEventArgs)
MsgBox("Needs to happen first.")
End Sub
End Class
I need MoveMouse in this class to fire before any other event when the user moves their mouse over Form1.
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
MsgBox("Needs to happen second.")
End Sub
While writing this, I realized I could create yet another custom event handler in Form1's class, but is there any other way to ensure that MoveMouse (regardless of what class it is in) happens before Form1_MouseMove?
Thanks-
~Nic
Events are fired in the order in which they are declared:
So if you want your custom class to raise MouseMove on Form1 before Form1 raises the event you need to make your custom class add the handler first:
Public Class CustomClass
Public Sub OnMouseMoved(sender As Object, e As MouseEventArgs)
Console.WriteLine("Custom mouse moved")
End Sub
End Class
Public Class Form1
Public Custom As CustomClass
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Custom = New CustomClass
AddHandler MouseMove, AddressOf Custom.OnMouseMoved
AddHandler MouseMove, AddressOf OnMouseMoved
End Sub
Private Sub OnMouseMoved(sender As Object, e As MouseEventArgs)
Console.WriteLine("Form1 mouse moved")
End Sub
End Class

vb.net call subroutine from form3

I have three Forms; Formone Mdi form, Formtwo non Mdi form and Formthree the child of Formtwo
I want when Formthree closes, to call a subroutine (RefreshData()) in Formtwo, this is what I have but not working. Thanks
Dim formone As New MainWindow
Dim formtwo As New AppFormData
Dim formthree As New UpdateAppForm
formtwo.MdiParent = Me.MdiParent
formtwo.RefreshData()
Me.DialogResult = Windows.Forms.DialogResult.OK
First, you make sure that formtwo's RefreshData() is declared as Public so it can be accessed from a different form rather than the form where it is created.
Like:
Public Sub RefreshData()
...
End Sub
Then regarding how you call it when formthree closes, you can use the Form_Closing event.
Private Sub formthree_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
formtwo.RefreshData()
End Sub
Better design will be to use events. This approach will work gracefully if you make Formthree as child of any other form as it is not depending on this parentform. Declare the event in Formthree and consume it in parentform i.e. Formtwo
Public Class Formthree
Public Event CallMethod()
Private Sub Formthree_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
RaiseEvent CallMethod()
End Sub
.
.
.
End Class
Public Class Formtwo
Private WithEvents frm3 As Formthree
.
.
.
Private Sub frm3_CallMethod() Handles frm3.CallMethod
RefreshData()
End Sub
End Class

Changing Controls of a form inside a panel

I am facing a weird problem
I have 3 forms: MainForm, Form1, Form2
MainForm has 1 Panel: Panel1
Form1 has 1 Label: NameLbl and Button: ChangeBtn
Form2 has 1 textbox: NameTxt and Button: SaveBtn
I used the following code to open form1 inside Panel1 in mainform
Panel1.Controls.Clear()
Dim FormInPanel As New Form1()
FormInPanel.TopLevel = False
Panel1.Controls.Add(FormInPanel)
FormInPanel.Show()
On ChangeBtn.Click Form2 opens as showdialog
I want NameLbl.text to change to NameLbl.text when SaveBtn is clicked But normal code doesnt work.
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
Form1.NameLbl.text=NameTxt.text
End Sub
What Should I do? Any suggestions? Given that i need to open the forms in panels for certain reasons.
Please keep in mind that this is just an example. I have multiple controls in Form1 which i want to change on form2.SaveBtn.click
I have also tried this but it does nothing
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
For Each c As Control In MainForm.Panel1.Controls(0).Controls
If c.Name="NameLbl" Then
c.Text = NameTxt.Text
End If
Next
End Sub
Please Somebody tell me how it do it!
Form2 doesn't seem to have any connection back to Form1 or MainForm. You'd need to raise an event from Form2 which MainForm handles or another class handles and can pass to MainForm
Edit:
Sorry, I've just seen how you're calling Form2. There are lots of ways to get a value back from Form2 after calling ShowDialog(). One is to create a property called Result and check Result if ShowDialog() == DialogResult.OK. Something like the following.
Public Class Form2
Inherits System.Windows.Forms.Form
Public Property Result() As String
Get
Return m_Result
End Get
Set
m_Result = Value
End Set
End Property
Private m_Result As String
End Class
Public Class Form1
Inherits System.Windows.Forms.Form
Public ChangeBtn As Button
Public NameLbl As Label
Public Sub New()
Me.ChangeBtn = New Button()
AddHandler Me.ChangeBtn.Click, AddressOf ChangeBtn_Click
Me.NameLbl = New Label()
End Sub
Private Sub ChangeBtn_Click(sender As Object, e As EventArgs)
Dim form As New Form2()
Dim dr = New form.ShowDialog()
If dr = DialogResult.OK Then
Me.NameLbl.Text = form.Result
End If
End Sub
End Class
I'd like to add that if you plan on growing this application much larger you'll run into issues with maintenance. Look into some patterns for dealing with UI logic like MVC, MVP, MVVM if you're interested.
you can try this code:
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
panel1.Controls(0).NameLbl.text=NameTxt.text '"0" is the index of forminpanel in panel1,maybe it need to change.
End Sub
Form1 is contained in Panel1, so you can not access it via
Form1.
Only MainForm is visible from Form2:
Private Sub SaveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveBtn.Click
For Each c As Control In MainForm.Panel1.Controls(0).Controls
If TypeOf c Is TextBox Then
c.Text = NameTxt.Text
End If
Next
End Sub
Try this:
For Each form1 As Form1 In MainForm.OwnedForms.OfType(Of Form1)
Form1.NameLbl.text = NameTxt.text
Next
I've faced same issue and I've fixed with this
Dim f As FormInPanel
f = Form.Panel1.Controls(0)
f.transection = True
f.NameLbl.text=NameTxt.text

How do I handle events with interfaces in VB.NET?

I'm new to interfaces and I'm trying to understand how they work.
I wrote the following code, which works properly except the click event which is not firing.
Public Class Form1
Dim WithEvents Button As IClass = New MyButton
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button.Parent = Me
End Sub
Public Sub ClickEventHandler(ByVal Sender As Object, ByVal E As EventArgs) Handles Button.Click
MsgBox("Piwpiw !")
End Sub
End Class
Public Interface IClass
Event Click(ByVal Sender As Object, ByVal E As EventArgs)
Property Parent
End Interface
Public Class MyButton
Inherits SimpleButton
Implements IClass
Public Event click1(ByVal Sender As Object, ByVal E As System.EventArgs) Implements IClass.click
Public Property Parent1 As Object Implements IClass.Parent
Get
Return MyBase.Parent
End Get
Set(ByVal value As Object)
MyBase.Parent = value
End Set
End Property
End Class
What's wrong with that code?
(PS: This is just an example allowing me to understand how interfaces work and doesn't have any functional meaning.)
You're missing a single method in the MyButton class to make this work.
You need this:
Private Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
RaiseEvent click1(sender, e)
End Sub
Essentially SimpleButton already has a click method. It's being raised when you click your derived MyButton class. But the Click event on SimpleButton isn't the same event as Click on the IClass interface. You implemented that as click1. So you just need to raise the click1 method when the Click method is raised. Hence the above method.
In your sample code, I don't see a line where the event is raised. In order to be able to handle an event in the event handler, you'd have a spot in your MyButton class that raises the event, i.e.:
Public Class MyButton
Inherits SimpleButton
Implements IClass
Public Event click1(ByVal Sender As Object, ByVal E As System.EventArgs) Implements IClass.click
Public Property Parent1 As Object Implements IClass.Parent
Get
Return MyBase.Parent
End Get
Set(ByVal value As Object)
MyBase.Parent = value
End Set
End Property
Public Sub SimulateClick()
RaiseEvent click1(Me, New System.EventArgs())
End Sub
End Class
You use the RaiseEvent statement to raise an event.
Above sample, of course, assumes that at some point in your code, you call SimulateClick instead of having a real mouse click (which would involve painting the button and reacting to several mouse events). Once the event is raised, your handler will be called. You could do this from your Form1_Load method:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button.Parent = Me
Button.SimulateClick()
End Sub
I have noticed that your MyButton class derives from a SimpleButton class. Instead of having the SimulateClick-method, you could also react to a click in the SimpleButton class and place the RaiseEvent statement there.
Here is the solution:
Replace MyButton class with:
Public Class MyButton
Inherits SimpleButton
Implements IClass
Public Shadows Event click(ByVal Sender As Object, ByVal E As System.EventArgs) Implements IClass.Click
Public Property Parent1 As Object Implements IClass.Parent
Get
Return MyBase.Parent
End Get
Set(ByVal value As Object)
MyBase.Parent = value
End Set
End Property
Public Sub ClickEventHandler(ByVal Sender As Object, ByVal E As EventArgs) Handles MyBase.Click
RaiseEvent click(Sender, E)
End Sub
End Class