WithEvents bug in Visual Studio 2015? - vb.net

I probably encountered an issue of Visual Studio 2015. If you define three handlers of the same event using WithEvents and Handles keywords, one of the handlers will not be called. I traced this behavior in our software and wrote following WinForms sample project.
Public Class MainBase1
Inherits Form
Protected WithEvents Button1 As Button
Protected TextBox1 As TextBox
Public Sub New()
SuspendLayout()
Text = "WithEvents Test"
ClientSize = New Size(300, 300)
Button1 = New Button()
Button1.Location = New Point(10, 10)
Button1.Size = New Size(100, 25)
Button1.Text = "Button1"
Controls.Add(Button1)
TextBox1 = New TextBox()
TextBox1.Location = New Point(10, 50)
TextBox1.Multiline = True
TextBox1.Size = New Size(280, 240)
Controls.Add(TextBox1)
ResumeLayout(False)
PerformLayout()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text &= "MainBase1: Button click handled." & vbNewLine
End Sub
End Class
Public Class MainBase2
Inherits MainBase1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text &= "MainBase2: Button click handled." & vbNewLine
End Sub
End Class
Public Class Main
Inherits MainBase2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text &= "Main: Button click handled." & vbNewLine
End Sub
End Class
After clicking Button1 Textbox1 contains
MainBase1: Button click handled.
Main: Button click handled.
If I compile the same sample under Visual Studio 2012, I get
MainBase1: Button click handled.
MainBase2: Button click handled.
Main: Button click handled.
Has anybody encountered this issue as well? Or have I missed something?

This bug still remains. Here is my solution to this.
I made the handler in MainBase1 Protected Overridable. Subclasses don't use Handles but override the handler and call MyBase.
This approach has the advantage that execution order of handlers is well-defined.
Public Class MainBase1
Inherits Form
Protected WithEvents Button1 As Button
Protected TextBox1 As TextBox
Public Sub New()
SuspendLayout()
Text = "WithEvents Test"
ClientSize = New Size(300, 300)
Button1 = New Button()
Button1.Location = New Point(10, 10)
Button1.Size = New Size(100, 25)
Button1.Text = "Button1"
Controls.Add(Button1)
TextBox1 = New TextBox()
TextBox1.Location = New Point(10, 50)
TextBox1.Multiline = True
TextBox1.Size = New Size(280, 240)
Controls.Add(TextBox1)
ResumeLayout(False)
PerformLayout()
End Sub
Protected Overridable Sub Button1_Click(sender As Object, e As EventArgs) _
Handles Button1.Click
TextBox1.Text &= "MainBase1: Button click handled." & vbNewLine
End Sub
End Class
Public Class MainBase2
Inherits MainBase1
Protected Overrides Sub Button1_Click(sender As Object, e As EventArgs)
MyBase.Button1_Click(sender, e)
TextBox1.Text &= "MainBase2: Button click handled." & vbNewLine
End Sub
End Class
Public Class Main
Inherits MainBase2
Protected Overrides Sub Button1_Click(sender As Object, e As EventArgs)
MyBase.Button1_Click(sender, e)
TextBox1.Text &= "Main: Button click handled." & vbNewLine
End Sub
End Class

Related

Can not change the value of a combobox in an user control from another form

I have an user control in Autocad that makes drawings based on certain criteria.
From this user control, another form can be opened which is used to fill in specific data.
When i try to automatically change the Combobox in the User Control with data from the Form, it gives the error:
Reference to a non-shared member requires an object reference.
Now I have looked this up on the internet, but I can not seem to apply the solutions given.
My situation is as follows:
Partial Public Class Partial Public Class User_Control
Private Form1 As New Form_Something
private sub button1_click(sender As Object, e As EventArgs) Handles button1.Click
Form1.show()
End sub
End Class
This User Control has got a Combobox, lets name it Combobox1. Now when i change a value on Form_Something, Combobox1 must change as well.
So I've got the following code in Form1:
Partial public class Form_Something
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles BT_Apply.Click
User_Control.Combobox1.text = "Apples"
End sub
End class
This gives the mentioned error.
Can someone please help me resolve this issue, because I'd like to do this with multiple comboboxes/labels etc.
To show you more intuitively, I changed the BorderStyle of UserControl1 here. You can change or comment it as needed.
I have commented on some key parts of the code, please let me know if you are still confused.
If my post helps to resolve your issue, please click the "Mark as Answer" of that post. By marking a post as Answered or Helpful, you help others find the answer faster.
The results are as follows:
My code are as follows:
1.Form1 code:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs)
MyUserControl.ComboBox1.Text = "Apples"
End Sub
End Class
2.UserControl1 code:
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBox1.Text = "Apple"
Me.BorderStyle = BorderStyle.Fixed3D
End Sub
Dim myForm As Form
Dim btn As Button
Dim txtbox As TextBox
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
myForm = New Form With {.Text = "myForm"}
btn = New Button With {.Text = "Save", .Height = 30, .Width = 60, .Top = 100, .Left = 150}
txtbox = New TextBox With {.Text = "", .Height = 20, .Width = 100, .Top = 100, .Left = 20}
myForm.Controls.Add(btn)
myForm.Controls.Add(txtbox)
myForm.Show() 'Open dialog in modeless window
AddHandler btn.Click, AddressOf Btn_Click
End Sub
Sub Btn_Click(sender As System.Object, e As System.EventArgs)
Me.ComboBox1.Text = txtbox.Text 'This step is important!
myForm.Close()
End Sub
End Class

how to navigate adorner when click button

I create a sample of adorner to inform client the use usage of each component.
What i want to ask is, how do i move the control/adorner to other component.
in the picture when i click the help button,it show the adorner. how do i move the adorner to the textedit2 purple square. the adorner using usercontrol.
this is the form1 code
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AdornerUIManager1.ShowGuides = DevExpress.Utils.DefaultBoolean.True
End Sub
Private Sub AdornerUIManager1_QueryGuideFlyoutControl(sender As Object, e As DevExpress.Utils.VisualEffects.QueryGuideFlyoutControlEventArgs) Handles AdornerUIManager1.QueryGuideFlyoutControl
If e.SelectedElement.TargetElement Is Button1 Then
e.Control = New LabelControl() With {
.AllowHtmlString = True,
.Width = 350,
.AutoSizeMode = LabelAutoSizeMode.Vertical,
.Padding = New Padding(20),
.Text = "<b>Navigation Bar</b><br>" & "A side navigation control that supports integration with Office Navigation Bar<br><br>" & "Shows navigation options for your currently selected module"}
End If
If e.SelectedElement.TargetElement Is TextEdit1 Then
Dim x As New UserControl1
x.Label1.Text = "xxXXXxx"
x.WindowsUIButtonPanel1.Buttons(0).Properties.Checked = True
e.Control = x
End If
End Sub
this is the usercontrol code
Public Class UserControl1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As Form1
x.AdornerUIManager1.Elements(0).TargetElement = x.TextEdit3
End Sub
End Class
when i try to click, it got error

Menu Item Custom Control Events

I am trying to create a menu list item that contains both a textbox and a label as a single item. In the code below I have made the necessary custom control class inherited from ToolStripControlHost and this looks and behaves as expected when created in the form menu.
The problem I am having is that the control's events are not firing the handler routine. In the example below, what I would expect to happen is that when the user types into the text box a message should show (other events have the same problem).
Thank you.
Control Classes:
Public Class ToolStripTextBoxWithLabel
Inherits ToolStripControlHost
Public Sub New(Optional ByVal lblText As String = "label")
MyBase.New(New ControlPanel(lblText))
End Sub
Public ReadOnly Property ControlPanelControl() As ControlPanel
Get
Return CType(Me.Control, ControlPanel)
End Get
End Property
End Class
Public Class ControlPanel
Inherits Panel
Friend WithEvents txt As New TextBox
Friend WithEvents lbl As New Label
Public Sub New(ByVal lblText As String)
Me.Height = 20
lbl.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Bottom
lbl.Text = lblText
lbl.TextAlign = ContentAlignment.BottomLeft
lbl.AutoSize = True
lbl.Height = Me.Height
lbl.Location = New Point(0, 3)
lbl.Parent = Me
txt.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
txt.Location = New Point(lbl.Right + 3, 0)
txt.Width = Me.Width - txt.Left
txt.Parent = Me
End Sub
End Class
Form Implementation:
Public Class Form1
Friend tb_SearchBox As ToolStripTextBoxWithLabel
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
tb_SearchBox = New ToolStripTextBoxWithLabel("Search:") With {.Name = "tb_SearchBox"}
AddHandler tb_SearchBox.TextChanged, AddressOf tb_SearchBox_TextChanged
Item1ToolStripMenuItem.DropDownItems.Add(tb_SearchBox)
End Sub
Private Sub tb_SearchBox_TextChanged(sender As Object, e As EventArgs)
MsgBox("Success")
End Sub
End Class
Using the TextChanged event of your ToolStripTextBoxWithLabel in this instance is inappropriate because that event should only be raised when the Text property of that object changes, which is not happening here. You need to do what Plutonix suggested but you should also do it with your own custom event rather than with the TextChanged event of the host, e.g.
Public Event TextBoxTextChanged As EventHandler
Protected Overridable Sub OnTextBoxTextChanged(e As EventArgs)
RaiseEvent TextBoxTextChanged(Me, e)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
OnTextBoxTextChanged(EventArgs.Empty)
End Sub
Rather than deriving your ControlPanel class from Panel and creating the child controls in code, I would suggest that you create a user control and add the children in the designer. You would then use my answer below in two steps, i.e. the user control would handle the TextChanged event of the TextBox and then raise an event of its own that would, in turn, be handled by the ToolStripTextBoxWithLabel that would its own event.
Thanks to jmcilhinney and Plutonix I have put together the solution. For completeness and future community reference the full solution is below.
User Control:
Public Class CustomTextBox
Public Event TextBoxTextChanged As EventHandler
Protected Overridable Sub OnTextBoxTextChanged(e As EventArgs)
RaiseEvent TextBoxTextChanged(Me, e)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
OnTextBoxTextChanged(EventArgs.Empty)
End Sub
Public Sub New (lblText as string)
InitializeComponent()
Caption = lblText
End Sub
Public Property Caption() As String
Get
Return Label1.Text
End Get
Set(ByVal value As String)
Label1.Text = value
End Set
End Property
Public Overrides Property Text() As String
Get
Return TextBox1.Text
End Get
Set(ByVal value As String)
TextBox1.Text = value
End Set
End Property
Public Class
Implementation:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim SearchBox As New CustomTextBox("Search")
Dim host As ToolStripControlHost = new ToolStripControlHost(windowNewMenu)
AddHandler SearchBox.TextBoxTextChanged, AddressOf SearchBox_TextChanged
ToolStripMenuItem1.DropDownItems.Add(host)
End Sub
Private Sub SearchBox_TextChanged(sender As Object, e As EventArgs)
MsgBox(sender.Text)
End Sub

form opening on load

My program was opening a different form to what I wanted it to. The answers solved it.
Basically I wanted to stop a form opening when the program started, but when it opened manually (on a button press), it updated the data. The second part of the problem has not been solved, but the first part has been.
You can try something like this:
Public Class HomeForm
Private WithEvents m_DataChangeForm As DataChangeForm
Private Sub HomeForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
m_DataChangeForm = New DataChangeForm()
m_DataChangeForm.Show()
End Sub
Private Sub OnDataSourceChanged(sender As Object, args As EventArgs) Handles m_DataChangeForm.OnDataSourceChanged
MessageBox.Show("Data source changed!")
End Sub
End Class
Public Class DataChangeForm
Inherits Form
Public Event OnDataSourceChanged(sender As Object, args As EventArgs)
Private WithEvents m_Button As Button
Public Sub New()
m_Button = New Button()
m_Button.Text = "Change"
m_Button.Parent = Me
End Sub
Public Sub buttonClick(sender As Object, args As EventArgs) Handles m_Button.Click
RaiseEvent OnDataSourceChanged(sender, args)
Me.Close()
End Sub
End Class
Reason your form is displayed before HomeForm is becaouse you call ShowDialog, it blocks until DataChangeForm is closed.
You should move your code from "Load" to "Shown" Event.
Private Sub Homefrm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Using fp = New dataChangefrm(m_database)
If fp.ShowDialog() = DialogResult.OK Then
uwgHome.DataSource = Nothing
loadData()
End If
End Using
Me.Location = New Point(0, 0)
loadData()
End Sub
Please have a look on the Handle in the first line. It depends on your Project.

VB.NET Me.Close() doesn't work, the form doesn't close?

The form is an About Us form so has nothing on it only a text box and a OK button.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
Here is how I'm opening the form:
Private Sub AboutAppStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutAppStripMenuItem.Click
Dim formAbout As New FormAbout()
formAbout.Show()
End Sub
Why won't the button close the form? I'm puzzled, I tried another button just in case with the same result.
UPDATE: I set a break point on Me.Close() and it isn't reaching it when I click the button, I created a new button and the same thing happened.
Thanks
I am betting the event handler for the button1_click event has been inadvertently removed.
Try double-clicking on the button in design time and see if it pulls you back to that same exact piece of code - or a new event handler definition.
If it's a new event handler definition - copy your code there and delete the first one.
There are other ways to manually add the event handler in the designer's code-behind - but maybe that's for a later progression.
From within VS click the "Show all files" button in solutions explorer. Grab us the code in .Designer.vb and paste it in here and we'll nail it down for you definitively.
Here's mine:
Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
_
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
_
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(131, 91)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(133, 50)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
Me.Button1.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
Friend WithEvents Button1 As System.Windows.Forms.Button
End Class
From MSDN:
Showing the control is equivalent to setting the Visible property to true. After the Show method is called, the Visible property returns a value of true until the Hide method is called.
when formabout is open
click on pause(break all) button in visual studio
click on step into in debug in visual studio
click on the close button in formabout
you will see which code is executed, if any
* edit *
another question
is formabout.enabled property is true?
I tested the following
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim f As New Form2
f.Show()
End Sub
End Class
Public Class Form2
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Me.Close()
End Sub
End Class
and did not have problems. As was suggested, re-create your button and code.
Add you Button Dynamically may solve the problem.
Place the following code in the load event of about Form.
Public Sub FormAbout_Load(ByVal sender as object,ByVal e as System.EventArgs)Handles Me.Load
Dim btn as new Button()
AddHandler btn.Click ,AddressOf _ClickToClose
End Sub
Private Sub _ClickToClose(ByVal sender as object,ByVal e as System.EventArgs)
Me.Close()
End Sub
Simple.
Select Project Properties from Solution Explorer.
Select Security tab to either uncheck "Enable ClickOnce..." or select "This is a full trust application".
Save the properties settings.
Solved.