Strategies for controlling cascading events for interdependent controls on a form?

J

Joergen Bech

Just out of curiosity: What is your favorite method of making sure
that anything that happens on a form, only happens in response to
a single, external event?

Take the example below. I have made it as simple as I could:

Put two textboxes on a form, paste the code and run it.
The idea is that whatever is typed in one box is displayed in the
other box, only reversed. This is a simple example of two repre-
sentations of the same data on a single form.

---snip---

Public Class Form1
Private _myText As String

Private Sub DisplayValues()
Debug.WriteLine("----------")
Debug.WriteLine(_myText)
Debug.WriteLine(ReverseString(_myText))

TextBox1.Text = _myText
TextBox2.Text = ReverseString(_myText)
End Sub

Private Function ReverseString(ByVal value As String) As String
Dim reverse() As Char = value.ToCharArray
Array.Reverse(reverse)
Return New String(reverse)
End Function

Private Sub TextBox1_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
_myText = TextBox1.Text
DisplayValues()
End Sub

Private Sub TextBox2_TextChanged(ByVal sender As Object, ByVal e
As System.EventArgs) Handles TextBox2.TextChanged
_myText = ReverseString(TextBox2.Text)
DisplayValues()
End Sub

End Class
---snip---

Problem is: If I start editing the value in TextBox1, I get a
TextBox1_TextChanged event, which will update the value
in TextBox2, which in turn causes TextBox2_TextChanged to
fire, which in turn ... and so on until the program runs out of
stack space.

We only want to respond to the first, external event, so the
natural inclination is to set a boolean variable which tells us
if an event is external or internal to the form. If internal, the
event should be ignored.

My own approach looks something like this:

Private Sub SomeObject_SomeEvent(...) Handles ...
If Me.AcceptEvents Then
Try
(update data)
DisplayValues
Finally
Me.EnableEvents
End Try
End Sub

All my forms are inherited from a base form class that implements
the AcceptEvents function and EnableEvents method.

AcceptEvents will return True *and* set the internal _acceptEvents
variable to False *if* _acceptEvents is True.

EnableEvents just sets _acceptEvents to True.

This allows me to enclose all my event code in as few lines as
possible(?), yet ensures that any event I process is only in response
to a single, external event (such as a mouseclick, keydown, etc).

The question is: Is there an elegant, generalized .Net way of
doing this or do you just add such boolean variables as you go
along, depending on whether or not the form needs it?

What I have works for me and I am quite happy with it, but I
would like to see other approaches to dealing with this problem.

Not looking for a solution to the specific sample, but general
approaches. Any suggestions?

Regards,

Joergen Bech
 
L

Lucas

Just out of curiosity: What is your favorite method of making sure
that anything that happens on a form, only happens in response to
a single, external event?

Take the example below. I have made it as simple as I could:

Put two textboxes on a form, paste the code and run it.
The idea is that whatever is typed in one box is displayed in the
other box, only reversed. This is a simple example of two repre-
sentations of the same data on a single form.

---snip---

Public Class Form1
Private _myText As String

Private Sub DisplayValues()
Debug.WriteLine("----------")
Debug.WriteLine(_myText)
Debug.WriteLine(ReverseString(_myText))

TextBox1.Text = _myText
TextBox2.Text = ReverseString(_myText)
End Sub

Private Function ReverseString(ByVal value As String) As String
Dim reverse() As Char = value.ToCharArray
Array.Reverse(reverse)
Return New String(reverse)
End Function

Private Sub TextBox1_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
_myText = TextBox1.Text
DisplayValues()
End Sub

Private Sub TextBox2_TextChanged(ByVal sender As Object, ByVal e
As System.EventArgs) Handles TextBox2.TextChanged
_myText = ReverseString(TextBox2.Text)
DisplayValues()
End Sub

End Class
---snip---

Problem is: If I start editing the value in TextBox1, I get a
TextBox1_TextChanged event, which will update the value
in TextBox2, which in turn causes TextBox2_TextChanged to
fire, which in turn ... and so on until the program runs out of
stack space.

We only want to respond to the first, external event, so the
natural inclination is to set a boolean variable which tells us
if an event is external or internal to the form. If internal, the
event should be ignored.

My own approach looks something like this:

Private Sub SomeObject_SomeEvent(...) Handles ...
If Me.AcceptEvents Then
Try
(update data)
DisplayValues
Finally
Me.EnableEvents
End Try
End Sub

All my forms are inherited from a base form class that implements
the AcceptEvents function and EnableEvents method.

AcceptEvents will return True *and* set the internal _acceptEvents
variable to False *if* _acceptEvents is True.

EnableEvents just sets _acceptEvents to True.

This allows me to enclose all my event code in as few lines as
possible(?), yet ensures that any event I process is only in response
to a single, external event (such as a mouseclick, keydown, etc).

The question is: Is there an elegant, generalized .Net way of
doing this or do you just add such boolean variables as you go
along, depending on whether or not the form needs it?

What I have works for me and I am quite happy with it, but I
would like to see other approaches to dealing with this problem.

Not looking for a solution to the specific sample, but general
approaches. Any suggestions?

Regards,

Joergen Bech

I have dealt with this issue by using different events and not the
"Changed" event. Try attaching your events to other members like
txtTextBox.KeyUp() or txtTextBox.KeyPress(). these events are
external and will not trigger other events when changed strings in
textboxs.

I have been a victim of this a few times, but NO MORE! lol

cheers!
 
L

Lucas

I have dealt with this issue by using different events and not the
"Changed" event. Try attaching your events to other members like
txtTextBox.KeyUp() or txtTextBox.KeyPress(). these events are
external and will not trigger other events when changed strings in
textboxs.

I have been a victim of this a few times, but NO MORE! lol

cheers!- Hide quoted text -

- Show quoted text -

Example from what you showed above...

Private Sub TextBox1_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox1.KeyPress
_myText = TextBox1.Text
DisplayValues()
End Sub
 
J

Joergen Bech

--- snip---
Example from what you showed above...

Private Sub TextBox1_TextChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles TextBox1.KeyPress
_myText = TextBox1.Text
DisplayValues()
End Sub

Yes, in this case you could get away with it because KeyPress,
MouseDown, etc etc per definition are "external" events (or user
events, if you like), but such a scheme requires that you stick to
a list of "safe" events. I am talking about a completely generic
system where everything happens in response to a single event
and no other events are accepted until everything has "come to rest"
again, so to speak.

An "external" event could also be if an object bound to a form
fires a custom Changed event and expect the form to reflect the
changes in that object, but not modify the object because of the
Changed event.

How about three complex usercontrols displaying different aspects
of a single object. When one usercontrol modifies a property of the
object, the object should raise a Changed event, which the other
usercontrols should use to display their aspect of the object.
In such a case the other usercontrols do not know - nor should they
care - that the change happened because of a KeyPress event in
another usercontrol.

Not sure I have made myself clear. I deal with graphical controls
with lots of interdependent objects with interactions that go some way
beyond the usual master-detail CRUD scenarios.

Regards,

Joergen Bech
 
L

Lucas

--- snip---








Yes, in this case you could get away with it because KeyPress,
MouseDown, etc etc per definition are "external" events (or user
events, if you like), but such a scheme requires that you stick to
a list of "safe" events. I am talking about a completely generic
system where everything happens in response to a single event
and no other events are accepted until everything has "come to rest"
again, so to speak.

An "external" event could also be if an object bound to a form
fires a custom Changed event and expect the form to reflect the
changes in that object, but not modify the object because of the
Changed event.

How about three complex usercontrols displaying different aspects
of a single object. When one usercontrol modifies a property of the
object, the object should raise a Changed event, which the other
usercontrols should use to display their aspect of the object.
In such a case the other usercontrols do not know - nor should they
care - that the change happened because of a KeyPress event in
another usercontrol.

Not sure I have made myself clear. I deal with graphical controls
with lots of interdependent objects with interactions that go some way
beyond the usual master-detail CRUD scenarios.

Regards,

Joergen Bech- Hide quoted text -

- Show quoted text -

Yes, I understand better now. I am not aware of any semaphores used
to delegate interactions between objects. I do know that what you
have described in the initial post seems to exactly what you
described.

Hopefully, others can give a better example than me.

cheers!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top