• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2174
  • Last Modified:

Stop TextChanged events firing


Have converted over a Vb6 application to Vb.Net

From the IntializeComponents rountine added by vb.net, on every initialization of every control it calls the TextChanged or ValueChanged events.

Microsoft recommend creating a property called IsInitializing and the checking this at the start of EVERY TextChanged event

This seems highly inefficient, and overkill.

Is there anyway of removing the InitializeComponents from firing on initialization of every control???
3 Solutions
The way Ms suggest is still the best way to go, but you can handle all your textbox.textchanged events in one go

Private Sub textbox_textChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles textbox1.TextChanged,textbox2.TextChanged,textbox3.TextChanged etc...
   If Form1.DefInstance.IsInitializing = True Then
      Exit Sub
      'Do your thing here
   End If
End Sub
Another option would be to use an AddHandler after the InitializeComponents call for the sub handling the TextChanged event, instead of using the Handles command on the sub declaration. This way you can control when you want your sub to start handling the TextChanged event.

So for example...

Public Sub New()

        'This call is required by the Windows Form Designer.

        'Add any initialization after the InitializeComponent() call
        AddHandler TextBox1.TextChanged, AddressOf Me.NameofSub
End Sub

StuartKAuthor Commented:
First off thanks for both of you replying.

Ronald - That'll reduce the code running, but unfortunately we use most if not all of the TextChanged event to change the state from View to Edit later in the code. (i.e. when form opened it shows data, if any textboxes are typed in, it automatically changes state to Edit - shows the Save button)
1.Some TextChange events do a raw make SaveButton.Enabled = True.
2. Some other do the same plus more.
3.And furthermore some others do above two plus a hell of a lot more.
So could consolidate majority, but not all. I feel that this, in my application, would lose standardisation of TextChanged events against limited gain in speed.
Guess it's an all or nothing.
A good suggestion though. I'll need to assess textchanged events

tgannetts -
Can you possibly elabourate on your suggestion.

The textchanged events will still fire won't they within the InitializeComponents function??

Once again thanks guys
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

If you do what tgannetts says it means that you do not use the handles keyword when you define the methods.ie normally you have
private sub textbox1_textchanged(sender as object,e as eventargs) handles textbox1.textchanged
end sub

Instead you define the methods as
private sub textbox1_textchanged(sender as object,e as eventargs)
end sub
note there is no handles keyword used and then you manually add a handler after the initialization to the textchanged event using
addhandler textbox1.textchanged, addressof textbox1_textchanged

thus the textchanged event will still be fired but it wont be handled anywhere during initialization since you are adding the handler after initialization.
I think what must be remembered is that the InitializeComponent does not call the TextChanged sub. Rather, the TextChanged sub is called by a separate thread which is created in response to an Event which in turn is raised as a result of something the InitializeComponent has done to the textbox.

The following code is an example of code from the InitializeComponent sub when a TextBox is to be created on a form:

      Me.TextBox1 = New System.Windows.Forms.TextBox()

      Me.TextBox1.Location = New System.Drawing.Point(8, 56)
      Me.TextBox1.Name = "TextBox1"
      Me.TextBox1.Size = New System.Drawing.Size(112, 20)
      Me.TextBox1.TabIndex = 1
      Me.TextBox1.Text = "Please enter text"

As soon as the 'Me.TextBox1 = New System.Windows.Forms.TextBox()' is called, Events will
be raised if the relevant actions, and occur whether you handle them or not.

When the TextBox constructor is called, it sets each of the controls properties to a default setting, so for example the Text property is set to nothing, and I believe the location is set to (0,0). When the InitializeComponent sets these properties to the values you have set through the IDE, an Event could occur for each one because the function changes the values set by the constructor. So a LocationChanged event will occur as the Control's location is changed to (8,56) and a SizeChanged event will occur because the Controls size is set to (112, 20). Depending on the control type, any number of Events could be raised just from the InitializeComponent sub setting the properties of a control to what you have specified in the IDE. If you have specifed an Event Handler for a certain event, the code in that sub will be processed.

In your example, it is most likely that the TextChanged event is being raised due to something the InitializeComponent is doing to the textbox. If you have set a Text Value for the text box, then the event will occur as soon as the [Me.TextBox1.Text = "Please enter text"] line is actioned by the sub. Be aware that a number of events will have been raised already, such as the LocationChanged event, and if you set Event Handlers for these then you can trap them.

The problem you are having is that you only want to trap the TextChanged event caused by a user. The Event Handler however traps all events which can occur as soon as the Constructor has been called. For example, if you have a button which resets the values in all the textboxes to default values, this will cause a TextChanged event to occur for each textbox.

I think therefore your options are either to add logic to the TextChanged sub as RonaldBiemans suggested, or use AddHandler and RemoveHandler to control when you want to trap the event.

Hope this is of some use.


StuartKAuthor Commented:
Thank you guys,

Great explanation to both of you in respect of handling events.

navneet77 - explained the fact of missing of the "Handles" bit of the Event itself
And then adding it in after InitializeComponents

This means that I can get rid of the IsInitializing = True in all the Text changed events. Extra code that isn't really required after the Initialisation

tgannetts - Great explanation into what the root cause of the InitializeComponents does in firing events. It makes absolute sense.

For the faxt that navneet77 made the penny drop and tgannetts for the original idea I'll split the points.

As for Ronald - just want to recognise that your solution didn't fit with mine, but is still a suitable idea that someone else reading this might relate more to their application.

It's ideal for people that have very similiar TextChanged events or whatever events duplicated accross the application.

Thanks to all guys helping me. It really was much appreciated.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now