Custom control mybase.OnTextChanged not firing - vb.net

I have a custom text box control which validates input (striped out unwanted chars). This works fine apart from when I also want to do further processing on an implementation of the control.
Example I have 3 "specialTextbox"s on a form. sText1, sText2 and sText3. sText1 & sText2 work as as intended. However, I need to make changes on the forum when the value of sText3 is changed, so I have a handler in the form to handle the ctext changed event:
Private Sub sText3(sender As Object, e As EventArgs) Handles sText3.TextChanged
'do some stuff here
End Sub
However this routine appears to override the OnTextChanged method of the custom text box. I have tried includeing a call to MyBase.OnTextChanged, but this still doesn't cascade up and no matter what I do I can't seem to get the text box to do its validation duties.
Must be something really simple, but I'm stumped!
Here is a class which overrides textbox
Public Class restrictedTextBox
Inherits Windows.Forms.TextBox
Protected validChars As List(Of Char)
Public Sub New(ByVal _validChars As List(Of Char))
MyBase.New()
validChars = _validChars
End Sub
Public Sub setValidChars(ByVal chrz As List(Of Char))
validChars = chrz
End Sub
Protected Overrides Sub OnTextChanged(e As System.EventArgs)
MyBase.OnTextChanged(e)
Dim newValue As String = ""
For Each c As Char In Me.Text.ToCharArray
Dim valid As Boolean = False
For Each c2 As Char In validChars
If c = c2 Then valid = True
Next
If valid Then newValue &= c.ToString
Next
Me.Text = newValue
End Sub
End Class
Here is a form which has a a custom textbox
Public Class frmNewForm
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnOK.Click
MessageBox.Show("the text from the restricted text is: " & txtRestricted.Text)
End Sub
End Class
Here is a form with a custom text box, which implements the TextChanged event
Public Class frmNewForm2
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnOK.Click
MessageBox.Show("the text from the restricted text is: " & txtRestricted.Text)
End If
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs) Handles txtRestricted.TextChanged
'now that I have implemented this method, the restrictedTextBox.OnTextChanged() doesn't fire - even if I call MyBase.OnTextChanged(e)
'just to be completely clear. the line of code below DOES get executed. But the code in restrictedTextBox.vb does NOT
lblAwesomeLabel.Text=txtRestricted.Text
End Sub
End Class

It fires, but probably not the way you are implementing it.
Your sample code does not have an empty constructor for the textbox, which means you are most likely not using the designer when you are adding the textbox to the form.
But your form shows it was created by the designer:
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs) _
Handles txtRestricted.TextChanged
End Sub
That's not possible with your posted code. If you are creating "new" controls programmatically, then you need to wire up the events programmatically, too.
Drop the handler and just leave the stub:
Private Sub txtRestricted_TextChanged(sender As Object, e As EventArgs)
'yada-yada-yada
End Sub
then when you create a new textbox, wire it up:
txtRestricted = new restrictedTextBox(myCharsList)
AddHandler txtRestricted.TextChanged, AddressOf txtRestricted_TextChanged
Me.Controls.Add(txtRestricted)

Related

cmbComboBox.SelectionStart always returns zero irrespective of cursor location

For some reason the "SelectionStart" property behaves differently from TextBox to ComboBox.
Create a TextBox and a ComboBox. Make sure DropDownStyle = DropDown (NOT DropDownList!)
Add these Leave events (same result if you use LostFocus event):
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
Debug.Print("Textbox: " & TextBox1.SelectionStart)
End Sub
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
Debug.Print("ComboBox: " & ComboBox1.SelectionStart)
End Sub
Now type text into each control and change focus from control to control, with the selection cursor in different places in the string.
I get this:
Textbox: 6
ComboBox: 0
Textbox: 8
ComboBox: 0
Textbox: 5
ComboBox: 0
Textbox: 4
ComboBox: 0
... and so on
When the textbox loses focus, it returns the correct SelectionStart.
When the combobox loses focus, it always returns zero.
Is there a reason, solution or reasonable workaround? I cannot seem to intercept this without creating a new variable for each combo control, and storing the SelectionStart on every click and keypress event (assuming the user might click the mouse, use arrow keys or type characters).
I just did some testing and it appears that the selection is reset between the Leave and LostFocus events as well as between the Enter and GotFocus events. I tried remembering the values on the first of each pair and restoring it on the second and it worked as desired:
Private comboBox1SelectionStart As Integer
Private comboBox1SelectionLength As Integer
Private Sub ComboBox1_Enter(sender As Object, e As EventArgs) Handles ComboBox1.Enter
comboBox1SelectionStart = ComboBox1.SelectionStart
comboBox1SelectionLength = ComboBox1.SelectionLength
End Sub
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
comboBox1SelectionStart = ComboBox1.SelectionStart
comboBox1SelectionLength = ComboBox1.SelectionLength
End Sub
Private Sub ComboBox1_GotFocus(sender As Object, e As EventArgs) Handles ComboBox1.GotFocus
ComboBox1.SelectionStart = comboBox1SelectionStart
ComboBox1.SelectionLength = comboBox1SelectionLength
End Sub
Private Sub ComboBox1_LostFocus(sender As Object, e As EventArgs) Handles ComboBox1.LostFocus
ComboBox1.SelectionStart = comboBox1SelectionStart
ComboBox1.SelectionLength = comboBox1SelectionLength
End Sub
You don't want to have to do that every time for every CokmboBox so you can build it into a custom control and then use that in place of the standard control:
Public Class ComboBoxEx
Inherits ComboBox
Private selectionStartTemp As Integer
Private selectionLengthTemp As Integer
Protected Overrides Sub OnEnter(e As EventArgs)
MyBase.OnEnter(e)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
End Sub
Protected Overrides Sub OnGotFocus(e As EventArgs)
'Restore the selection.
SelectionStart = selectionStartTemp
SelectionLength = selectionLengthTemp
MyBase.OnGotFocus(e)
End Sub
Protected Overrides Sub OnLeave(e As EventArgs)
MyBase.OnLeave(e)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
'Restore the selection.
SelectionStart = selectionStartTemp
SelectionLength = selectionLengthTemp
MyBase.OnLostFocus(e)
End Sub
End Class
A side-effect of this is that you will see the text selected even when the control doesn't have focus. The ComboBox has no HideSelection property like the TextBox does. If you don't like this then I'd imagine that you could find a way to make it behave like the TextBox does but that's a different question so I won't go into it here.
I think I've got it, using your idea but just setting the value in a different location.
Dim ComboSelectionStart As Integer
Private Sub cmbComboBox_KeyUp(sender As Object, e As KeyEventArgs) Handles cmbComboBox.KeyUp
'Store selection on any key press
ComboSelectionStart = cmbComboBox.SelectionStart
End Sub
Private Sub cmbComboBox_MouseClick(sender As Object, e As MouseEventArgs) Handles cmbComboBox.MouseClick
'Store selection on any mouse click
ComboSelectionStart = cmbComboBox.SelectionStart
End Sub
Private Sub cmbComboBox_Leave(sender As Object, e As EventArgs) Handles cmbComboBox.Leave
'Returns correct value here because it was not altered by LostFocus event
Debug.Print(ComboSelectionStart .ToString)
End Sub
When you modify the OnLeave() sub in the class provided by #jmcilhinney it actually works nicely.
Protected Overrides Sub OnLeave(e As EventArgs)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
MyBase.OnLeave(e) 'this has to go last because it modifies the SelectionStart...
End Sub

VBNET: How to Reset ComboBox after selection is made

How do I reset a ComboBox to default Text i set in properties. Say I have a ComboBox with default text "Ruby" which when SelectedIndexChanged is printed in TextBox afterwards it does'nt reset to default text "Ruby" but the SelectedItem. I want it to read "Ruby" afterwards or all the time if not possible. Thank you
Declare the helper class variable in the form class:
Dim _originalComboText As String
On opening the form, remember the default text of the control in some helper variable. For example, add the following line into the constructor (Sub New()):
_originalComboText = ComboBox1.Text
Every time after the selection is made, restore the text from it:
ComboBox1.Text = _originalComboText
If you inspect the content of the .designer.vb file belonging to your form, you can actually see initialization of text of your control through the assignment (=) – so vb.net does no special magic here. If you want to preserve the text, you have to save it somewhere before it gets lost.
Here is the complete minimum example:
Public Class Form1
Dim _originalComboText As String
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_originalComboText = ComboBox1.Text
End Sub
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
ComboBox1.Text = _originalComboText
End Sub
Private Sub ComboBox1_LocationChanged(sender As Object, e As EventArgs) Handles ComboBox1.LocationChanged
ComboBox1.Text = _originalComboText
End Sub
End Class
And if your two handlers do not differ, then replace them just with one – with two events in Handles clause:
Private Sub ComboBox1_RestoreText(sender As Object, e As EventArgs) _
Handles ComboBox1.Leave, ComboBox1.LocationChanged
ComboBox1.Text = _originalComboText
End Sub
Use this:
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
ComboBox1.Text = "Ruby"
End Sub
Private Sub ComboBox1_LocationChanged(sender As Object, e As EventArgs) Handles ComboBox1.LocationChanged
ComboBox1.Text = "Ruby"
End Sub
Since the user will choose, say print <<"EOF"; ---mytext---EOF from dropdown list and this will automatically print on textbox. He or she must go to textbox or somewhere else.
I know its not coventional to answer own question but if anyone needs help. Here it is

how to populate combobox in a usercontrol from an array in a class

I have a program in vb.net with a class and an usercontrol with a combobox. I want to populate the combobox with an array in the class. If user selects a value in combobox in usercontrol and return that value into class. I tried lot but there is no use.
Is it possible? If yes, then please guide me how to do it.
I have written the code for usercontrol as container1 as follows:
Private Sub container1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each i As Double In yl
Me.ComboBox1.Items.Add(i)
Next
End Sub
ERROR: Name yl is not declared.
yl is an array in my main class in the program.
thanks in advance
gvg
Ok you can do this in four steps:
Create a custom event in the usercontrol that fires when the selectedindex in the combobox is changed
Create a function that populates the combobox
Create a readonly property in your class that returns the items for the combobox
Mix this all together in the base form
First add some functionality to your userform
Public Class CtrlBox
'This is a usercontrol, created in VS
'The designer is not shown in this example
'This event is used to relay changes to the combobox to the outside world
Public Event ComboboxSelectionChanged(ByVal NewIndex As Integer, ByVal NewText As String)
'This Sub sets the combobox items
Public Sub SetComboboxItems(Newitems() As String)
Me.ComboBox1.Items.Clear()
Me.ComboBox1.Items.AddRange(Newitems)
End Sub
'Here the custom event is raised
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
RaiseEvent ComboboxSelectionChanged(Me.ComboBox1.SelectedIndex, Me.ComboBox1.Items(Me.ComboBox1.SelectedIndex).ToString)
End Sub
End Class
The class that will contain the selected index is called clsStuff. Notice the readonly property I use to return the desired items in the combobox
Public Class clsStuff
'This is like a constant that returns the items you
'want to add to the combobox
Public ReadOnly Property CustomComboItems As String()
Get
Return {"Test 1", "Test 2", "Test 3", "Test 4"}
End Get
End Property
'This variable shall store the selected string
Public SomeString As String = ""
End Class
Then bring it all together in your main form
Public Class Form1
'Drag the usercontrol containing the combobox onto your form
'This object is the one used to populate the combobox
'and store the selected item
Dim StuffObj As clsStuff
'Here the object is initialized and the CB-Items are set
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
StuffObj = New clsStuff
Me.CtrlBox1.SetComboboxItems(StuffObj.CustomComboItems)
End Sub
'Here the custom event is handled and used to change the
'string in the object
Private Sub CtrlBox1_ComboboxSelectionChanged(NewIndex As Integer, NewText As String) Handles CtrlBox1.ComboboxSelectionChanged
If StuffObj IsNot Nothing Then
StuffObj.SomeString = NewText
MsgBox("Updated property in object: " & StuffObj.SomeString)
End If
End Sub
End Class
This scheme should work well for your needs.
It is not a good way to access main program variable from the UserControl, although there is Parent property.
(1), you should create a AddItems() method to add the items as follow in your UserControl.
Public Sub AddItems(ByVal yl As String())
ComboBox1.Items.Clear()
For Each i As String In yl
ComboBox1.Items.Add(i)
Next
End Sub
(2), create a SelectedText() read-only property as follow
Public ReadOnly Property SelectedText()
Get
Return ComboBox1.Text
End Get
End Property
(3), create an event SelectedIndexChanged
Public Event SelectedIndexChanged()
(4), fire the event
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
RaiseEvent SelectedIndexChanged()
End Sub
(5), you can add items in your main form like this
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim yl() As String = {"Aa", "Bb", "Cc"}
Container1.AddItems(yl)
End Sub
(6), you can catch SelectedIndexChanged() event in your main form
Private Sub Container1_SelectedIndexChanged() Handles Container1.SelectedIndexChanged
Me.Text = Container1.SelectedText
End Sub

Using handlers across multiple forms?

I have code that highlights the current textbox in focus in order to provide a visual cue to the user. My question is, if I had 10 forms with textboxes and I wanted to provide this same code to them all. Would I have to duplicate it or can I use a global method? If so, an example would be very helpful. Thanks.
The code is as follows.
Private Sub FocusChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim txt As TextBox = sender
If txt.Focused Then
txt.Tag = txt.BackColor
txt.BackColor = Color.AliceBlue
Else
txt.BackColor = txt.Tag
End If
End Sub
Private Sub CreateAccount_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each ctrl As TextBox In Me.Controls.OfType(Of TextBox)()
AddHandler ctrl.GotFocus, AddressOf FocusChanged
AddHandler ctrl.LostFocus, AddressOf FocusChanged
ctrl.Tag = ctrl.BackColor
Next
End Sub
If you want to add this behavior to all TextBox controls, you're better off deriving your own class from the TextBox class, and override the OnGotFocus and OnLostFocus methods to set the properties accordingly.
Here's how:
Public Class MyTextBox
Inherits TextBox
Protected Overrides Sub OnGotFocus(e As System.EventArgs)
MyBase.OnGotFocus(e)
Me.Tag = Me.BackColor
Me.BackColor = Color.Aqua
End Sub
Protected Overrides Sub OnLostFocus(e As System.EventArgs)
MyBase.OnLostFocus(e)
Me.BackColor = Me.Tag
End Sub
End Class
EDIT: forgot to mention that after adding that class to your project, rebuild the solution, and if it compiles without errors, then your new TextBox class show show up in the VS ToolBox. You can then simply drag & drop onto your form just as any control.
Cheers

TextBox1 doesn't show the listbox1 value

I'm Visual Basic beginner, yesterday i wrote a dictionary that give you the opposite of the entered word, so i designed the form to look like this
[url]http://img651.imageshack.us/img651/6115/errorbp.jpg[url]
by the way i made a two list boxes as databases so the code will compare if the textbox1.text = listbox1.text then it will command textbox2 to append the value of the listbox : textbox2.appendtext(listbox2.text) but nothing happens
my code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub TnsBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If TextBox1.Text = TextBox3.ToString Then
TextBox2.AppendText(ListBox2.Text)
ElseIf TextBox1.Text = TextBox4.Text Then
TextBox2.AppendText(ListBox1.ToString)
End If
End Sub
Private Sub AddBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
ListBox1.Items.Add(TextBox3.Text)
ListBox2.Items.Add(TextBox4.Text)
End Sub
End Class
the point of the code is ok cuz yesterday i finished the coding and the programs works fine but i forget to save it so i coded again and every thing above happens
this is the yesterday program
http://www.mediafire.com/?tavne7xjyth7y7v
virustotal link:
https://www.virustotal.com/file/1d39429ae1498a744e1556188b7e8914526b7e2fbb2d4904c2b4ea22fb278dc7/analysis/1346676641/
Initially you are setting the textbox text to "ListBox" without choosing anything specific so it is calling ToString() on the listbox which is why you get that.
I would change the method so that you have a Dictionary variable like so:
Public Sub Translate(input As String)
TextBox2.Text = OppositeDictionaires(input)
End Sub
Public OppositeDictionary As New Dictionary(Of String, String)
'Call as Add(TextBox3.Text, TextBox4.Text)
Public Sub Add(input As String, opposite As String)
OppositeDictionary.Add(input, opposite)
End Sub
Call add from your event and then Translate from your translate event. You should then get your output as intended, still add them to the listboxes if you want to display to the user but handle the translation in the code behind through a dictionairy object.
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx