Stopping Multiple Events from Looping
I have a function that is intended to allow my user to move a set of objects (an airport) to a new location.
On the dialog that for this I have four controls - two textboxes that represent coordinates and two numeric up downs one for distance and one for bearing. The user can choose to enter either a distance and bearing or a set of coordinates. This is done via a checkbox and the non used set is disabled. So that the user has feedback I would like to update the disabled pair values as the user enters the enabled pair. If they are entering coordinates then the distance and bearing updates and vice versa.
My method for doing this is to respond to the TextChanged event of each object to update the others. Of course this creates one event firing another and back again as the other control updates. It does not create an infinite loop as far as I can开发者_Go百科 tell but it does mess up the caret position in the active boxes.
I have tried some approaches including including trying to disable events based on which boxes are active or using some bool flags. I also tried using a timer rather than events. It is all very messy and no approach seems to work. I would like to know if there is a better way.
Thanks
Assuming you are using Windows Forms:
// this.ckPosition.CheckedChanged += new System.EventHandler(this.ckPosition_CheckedChanged);
private void ckPosition_CheckedChanged(object sender, EventArgs e)
{
txtX.Enabled = txtY.Enabled = ckPosition.Checked;
numBearing.Enabled = numDistance.Enabled = !ckPosition.Checked;
}
// this.txtX.TextChanged += new System.EventHandler(this.Position_TextChanged);
// this.txtY.TextChanged += new System.EventHandler(this.Position_TextChanged);
private void Position_TextChanged(object sender, EventArgs e)
{
if (ckPosition.Checked)
{
// Replace with your calculations
numBearing.Value = Convert.ToInt32(txtX.Text);
numDistance.Value = Convert.ToInt32(txtY.Text);
}
}
// this.numBearing.ValueChanged += new System.EventHandler(this.BearingDistance_ValueChanged);
// this.numDistance.ValueChanged += new System.EventHandler(this.BearingDistance_ValueChanged);
private void BearingDistance_ValueChanged(object sender, EventArgs e)
{
if (ckPosition.Checked == false)
{
// Replace with your calculations
txtX.Text = numBearing.Value.ToString();
txtY.Text = numDistance.Value.ToString();
}
}
As long as you don't change the position in the position event handler or the bearing/distance in it's handler, there should not be any 'looping' of events.
I know this is probably a big performance no-no but have you tried finding the origin of your event using reflection to tell if it's a forwarded event or not? you could look further up the stack to find out if the event is a forwarded event, or you could abort if the call stack depth gets ridiculous. Or, if you're calling TextChanged events manually, you could derive from the eventArgs class to pass your own custom eventArgs and then abort if the eventArgs is your custom type or use the custom eventArgs to pass state information to help you. Or maybe you could swap the TextChanged event that sits on the control with a similar event handler of your own.
精彩评论