Soon I asked for help to read properties of textbox which is inside usercontrol.
Accessing to control inside of usercontrol
As I have been suggested I make one very simple public class with name xTextBox and use it as textbox in my usercontrol. That work fine.
Public Class xTextBox
Inherits TextBox
End Class
Now I can simply read a property on that xTextbox from main program which contain that usercontrol:
Dim s As Integer = myUserControl.xTextBox1.SelectionStart
But now is a problem that I can't get events of that Textbox in main program.
Maybe I can declare 'Shadows Event TextChanged...' etc, but I will need more events in different situations where usercontrol would be, and intentionally raising every of them don't look elegant in mean of practical programming.
How to get events of those xTextbox to main program?
If the your new UserControl has only one control and Inherits TextBox, then you can just attach the events like normal, either with the Property Editor, or Manually with AddHandler. If things are more complicated than that I would probably create a panel and put your new TextBox's in it, then it will be a lot easier to access the events.
Public Class myUserControl
Inherits TextBox
End Class
Public Class Form1
Public Sub New()
InitializeComponent()
AddHandler MyUserControl1.TextChanged, AddressOf MyUserControl_textChanged
End Sub
Private Sub MyUserControl_textChanged(sender As Object, e As EventArgs)
Throw New NotImplementedException
End Sub
End Class
Or if your UserControl has Multiple Custom TextBox's in it, you can create a Custom Event and fire that in a common TextChanged Event on your UserControl and handle that in your Main Form.
Public Class UserControl1
Public Event TextChange(sender As Object, e As EventArgs)
Private Sub MyUserControl_TextChanged(sender As System.Object, e As System.EventArgs) Handles MyUserControl1.TextChanged, MyUserControl2.TextChanged
RaiseEvent TextChange(sender, e)
End Sub
End Class
Public Class Form1
Public Sub New()
InitializeComponent()
End Sub
Private Sub UserControl11_TextChange(sender As System.Object, e As System.EventArgs) Handles UserControl11.TextChange
MsgBox(CType(sender, TextBox).Name, MsgBoxStyle.Information)
End Sub
End Class
Related
I have a usercontrol form named "ucSETTINGS", where there is a textbox and once the button was clicked, the text inside the textbox will be added to the combobox from another usercontrol form name "ucITEMS"
I tried this code but it's not working
(cboCategory is the name of the combobox from ucITEMS, txtNAME is the textbox from ucSETTINGS)
Private Sub btnSAVE_Click(sender As Object, e As EventArgs) Handles btnSAVE.Click
Dim category As New ucITEMS()
category.cboCATEGORY.Items.Add(txtNAME.Text)
End Sub
Can someone help me?
In this sort of situation, the user controls don't know about each other by default and it should stay that way. The source UC just exposes an interface and lets whomever is watching use that as it sees fit. That means raising an event when something happens and exposing required data via properties, e.g.
Public Class SourceControl
Public ReadOnly Property TextBox1Text As String
Get
Return TextBox1.Text
End Get
End Property
Public Event Button1Click As EventHandler
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
OnButton1Click(EventArgs.Empty)
End Sub
Protected Overridable Sub OnButton1Click(e As EventArgs)
RaiseEvent Button1Click(Me, e)
End Sub
End Class
The Text of the TextBox is exposed via a property and, when the user clicks the Button, the UC raises an event.
The destination UC provides an interface for new items to be provided but it adds them to its own ComboBox, e.g.
Public Class DestinationControl
Public Sub AddItemToComboBox1(item As Object)
ComboBox1.Items.Add(item)
End Sub
End Class
The form then plays go-between, handling the event, getting the property and calling the method:
Private Sub SourceControl1_Button1Click(sender As Object, e As EventArgs) Handles SourceControl1.Button1Click
DestinationControl1.AddItemToComboBox1(SourceControl1.TextBox1Text)
End Sub
Obviously you would use something more specific and appropriate than my generic naming.
I am kinda new to visual basic and was wondering if it is possible to trigger events in a class, based on action with in form.
So the following is my problem:
I have a form called Main, with a picture box called picPID
And a class called add_new
What I want to do is:
when the right mousebutton is clicked, the code for the event handling is placed within the class called add_new
I thought i could just declare it in the following way:
Sub meMouseDown(sender As Object, e As MouseEventArgs) Handles Main.picPID.MouseDown
But I get an error saying i have to declare it withEvents, I tried to declare the picturebox as:
Public shared withEvents as picturebox
but it dident help, any sugestions? It is not a problem having the code within the Main form, but it would result in a lot of code, so I was hoping to split it up.
So you have the class with an eventhandler:
Public Class add_new
Public Sub PictureBoxEventHandler(sender As Object, e As MouseEventArgs)
'Your Implementation
End Sub
End Class
Then you need an instance of this class within the form containing the picturebox:
Public Class Form1
Private add_New_Command As New add_new ' hold a reference to the command
'constructor
Public Sub New()
InitializeComponent()
' and add the handler to the event of the picture box ... hook it up
AddHandler PictureBox1.MouseDown, AddressOf add_New_Command.PictureBoxEventHandler
End Sub
End Class
I am experiencing a strange behaviour when using RightToLayout layout:
My form automatically closes.
I have created a simple project to reproduce the problem:
Create a new VB.NET project in VS2012 and add forms "Form1" and "Form2" to it.
Set "Form1" to be the start form.
Then add the following code to "Form1":
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Hide()
Dim f As New Form2
f.ShowDialog()
MessageBox.Show("After dialog closed.")
modControls.setFormRTL(Me) 'This line causes the Form2 to automatically close. Why??? This line should only be processed AFTER the dialog has been shown and closed
End Sub
End Class
Add the following code to "Form2":
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
modControls.setFormRTL(Me)
End Sub
End Class
Add a module with the name "modControls" to the project.
Add the following code to it:
Module modControls
Public Sub setFormRTL(ByVal uForm As Form)
uForm.RightToLeft = RightToLeft.Yes
End Sub
End Module
Without the setFormRTL, my project works perfectly fine, but with it, "Form2" automatically closes down. You can see this because the messagebox is shown.
When I remove the line
modControls.setFormRTL(Me)
from Form1 load, it works fine again.
Yes, I really mean from "Form1", not from "Form2"!!!
Now this is really strange because it should not matter at all because this line is not processed before the dialog is closed.
I hope somebody understands what I mean.
Can anybody shed some light on what might be happening here?
Yes, you'll get unexpected behavior if you set the RightToLeft property anywhere other than a control's constructor (in VB.NET parlance, that's the New method).
In fact, the constructor is where you should set all of the properties of a form or control object. If you come from VB 6, it might seem logical to do it in the Load event handler, but that's not idiomatic .NET and, as you've discovered, can cause problems when initializing certain properties.
The technical reason for this is that certain properties (like RightToLeft) can actually only be set on the native window (which is how the Form objects used in the .NET world are implemented behind the scenes) at the time that it is created. When you attempt to change the property, the framework code actually has to destroy and then re-create the native window with the new property values.
Change the code to look like this instead:
Public Class Form1
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
modControls.SetFormRtl(Me)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Hide()
Dim f As New Form2
f.ShowDialog()
MessageBox.Show("After dialog closed.")
End Sub
End Class
Public Class Form2
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
modControls.SetFormRtl(Me)
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
End Sub
End Class
Speaking of non-idiomatic .NET code:
Methods should all be Pascal cased by convention. That means your setFormRTL method should be named SetFormRtl.
A helper function that sets the properties of an object just seems wrong to me. If anything, that's just bad OO design. If you want this method to be available for all of your Form objects, derive a custom form class and add this method (or even do the desired initialization in the constructor). Either way, all forms that you derive from this custom form object will inherit the functionality. Example:
Public Class MyCustomForm : Inherits System.Windows.Forms.Form
Public Sub New()
MyBase.New()
Me.SetRtl()
End Sub
Public Sub SetRtl()
Me.RightToLeft = RightToLeft.Yes
End Sub
End Class
Public Class Form1 : Inherits MyCustomForm
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Hide()
Dim f As New Form2
f.ShowDialog()
MessageBox.Show("After dialog closed.")
End Sub
End Class
Public Class Form2 : Inherits MyCustomForm
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
End Sub
End Class
can you try this? all i am doing here is setting the RTL before the form is displayed.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Hide()
Dim f As New Form2
modControls.setFormRTL(f)
f.ShowDialog()
MessageBox.Show("After dialog closed.")
modControls.setFormRTL(Me)
End Sub
End Class
and remove code form load event of form 2
I have a little problem here. I'm trying to transfer/pass/raise the events of an owned form to his parent. Lets look at my example:
Lets say i have a form that initialize a CustomPanel (simply a class that inherits from System.Windows.Forms.Panel). It also have an event handler (it could be an other event, not necessarily a click event):
Public Sub New()
Me.Size = New Size(1000,1000)
Dim pnl1 As New CustomPanel()
pnl1.Location = New Point(0,0)
pnl1.size = New Size(100,100)
Me.Controls.Add(pnl1)
End Sub
Private Sub form1_Click(sender As Object, e As EventArgs) Handles Me.Click
MsgBox("I got it!")
End Sub
I did something similar and when I clicked on the CustomPanel (pnl1) the parent container (form1) did not receive a click event ... which is understandable. I tried to look in the properties of the CustomPanel (pnl1) if i could find something interesting like "click through" or "raise event to parent" (I was desperate here) but without success. I said alright, I will handle the events that I need to pass to parent in the CustomPanel class but I cant find a solution here neither:
Imports System.Windows.Forms
Public Class CustomPanel
Inherits Panel
Public Sub New()
End Sub
Private Sub CustomPanel_Click(sender As Object, e As EventArgs) Handles Me.Click
'What to put here?
'Me.Parent.?
End Sub
End Class
I just want to know if its possible to throw/raise/pass events to the parent. One thing is sure, its that i shouldn't have to and i cannot add anything else to the parent form. The reason is simple, i could have over 100 controls in this parent form and they could be added dynamically. And on top of that, these controls could also have their own controls inside! So i could have something like:
pnl99 call parent click -> pnl98 call parent click -> ... until the parent of the control really handle the click event ... -> form1 perform click event
Maybe its hard to understand but if you can help me I would appreciate.
Using a custom event, that the form owning the panel subscribes to. Raise Event
Public Sub New()
Me.Size = New Size(1000,1000)
Dim pnl1 As New CustomPanel()
pnl1.Location = New Point(0,0)
pnl1.size = New Size(100,100)
Addhandler pnl1.MyClickEvent, AddressOf pl_Click
Me.Controls.Add(pnl1)
End Sub
Private Sub pl_Click()
MsgBox("I got it!")
End Sub
Custom panel:
Public Class CustomPanel
Inherits Panel
Public Event MyClickEvent
Private Sub CustomPanel_Click(sender As Object, e As EventArgs) Handles Me.Click
RaiseEvent MyClickEvent()
End Sub
End Class
On the child form
Imports System.Windows.Forms
Imports STAS_PLC_Link_Lib
Public Class ChildForm
Public Event MyClick()
'.....rest of code
On the parent form
Public Class ParentForm
Private Sub GetSomeClick() Handles ChildFor.MyClick
System.Console.WriteLine("test")
End Sub
end Class
I have a class A which contains 2 user controls declared as
Friend WithEvents CustInfo1 As WindowsApplication1.CustInfo
Friend WithEvents ServiceLocation1 As WindowsApplication1.ServiceLocation
Both have textBoxes. If value of textBoxA in custInfo1 changes then how can I make value of textBoxB in SeviceLocation1 also change
I will be most thankful if anyone can help me.
Thanks
You need to do the following:
Inside the CustInfo user control, you need to write code inside the textBoxA Changed event that raises an event from the CustInfo user control (e.g. TextBoxChanged event). RaiseEvent statement
Inside the ServiceLocation user control, create a public property getter and setter for whatever your textBoxB.Text is
On the form that contains both user controls, create code in the new CustInfo TextBoxChanged event and set the new property on the ServiceLocation1 user control.
All controls (also custom controls) have the property Controls, through which you can access the (sub) controls of that control. Now you can retrieve your textbox by calling the .Item(key) method on it. Then you can assign a event handler to it in your form or class.
Dim key As String = "textBoxA" 'Or simply the name of that TextBox in your CustInfo
Dim textboxA As TextBox = CustInfo1.Controls.Item(key)
AddHandler textBoxA.TextChanged, AddressOf mytextchangedhandler
Where that mytextchangedhandler handles the TextChanged event for that TextBox.
Personally I don't like this method too much, as you are relying on knowing either the name of the TextBox or the index in the Controls list of your usercontrol.
I would definitely go for the option to create your own event on your usercontrol. It is quite easy to do even! Below how to do it. In the code behind of your usercontrol, you'll have to add an event declaration:
Event MyTextBoxChanged(sender As Object, e As EventArgs)
Now we'll have to raise it, we do this by implementing the TextChanged event of the TextBoxA in your usercontrol (as you explained you wanted to do):
Private Sub TextBoxA_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBoxA.TextChanged
RaiseEvent MyTextBoxChanged(Me, EventArgs.Empty)
End Sub
Now we can simply implement this event (MyTextBoxChanged) in your Form as follows:
Private Sub CustInfo1_MyTextBoxChanged(sender As System.Object, e As System.EventArgs) Handles CustInfo1.MyTextBoxChanged
' Do something
End Sub
Obviously we still need to get the updated text, now we can create our own EventArgs that will give us the new (and/or old value) as you will want to have. We simply can inherit the System.EventArgs class and add some properties (for example a property OldText that holds the old text value and a property NewText that holds the new text value):
Public Class MyEventArgs
Inherits System.EventArgs
Private _OldText As String
Public ReadOnly Property OldText() As String
Get
Return _OldText
End Get
End Property
Private _NewText As String
Public ReadOnly Property NewText() As String
Get
Return _NewText
End Get
End Property
Public Sub New(oldText As String, newText As String)
_OldText = oldText
_NewText = newText
End Sub
End Class
Now we have to change the event definition and raising to use the MyEventArgs:
Event MyTextBoxChanged(sender As Object, e As MyEventArgs)
Private Sub TextBoxA_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBoxA.TextChanged
RaiseEvent MyTextBoxChanged(Me, New MyEventArgs(TextBoxA.Text))
End Sub
And also change the implementation in your Form:
Private Sub CustInfo1_MyTextBoxChanged(sender As System.Object, e As MyEventArgs) Handles CustInfo1.MyTextBoxChanged
MessageBox.Show(e.Text)
End Sub
More information about events can be found on our favorite spot MSDN.