简体   繁体   中英

Best way to handle controls automatically updating each other?

I have a question regarding updating Controls in .Net in such a way so that if the user updates one field, the other field will be updated with some data automatically and vice versa. I am using two NumericUpDown controls which convert some data.

The problem I am having is that, I am using the ValueChanged event. Because of this, sometimes these controls get stuck in a loop where one controls updates the other and the other tries to update the first one. The result is somewhat random.

So, what would be the best approach to handle this situation? In short, I only want to update the other control, if the first one was modified by a user himself.

Any help would be greatly appreciated.

If method Foo handles the event of one control and method Bar handles the event for the other, then Foo should change the values of Bar 's control and vice-versa. But you should use a control variable somewhere (say, a reference to the control that fired the event is a good idea). So that if Foo is called:

  • Foo updates the value of Bar 's control;
  • Bar 's control fires its event, and Bar is called;
  • Bar checks the reference for the control that shot first, sees that it's not its control, and does nothing.

Same logic applies to Bar .

that way you don't get an infinite loop.

In code, it'd, look like this:

nud1.ValueChanged += new Eventhandler(Foo);
nud2.ValueChanged += new Eventhandler(Bar);
NumericUpDown shooter = null;

private void Foo (object sender, EventArgs e)
{
    if (this.shooter == null)
    {
        this.shooter = nud1;
        nud2.Value = nud1.Value;
    }
    else this.shooter = null;
}

private void Bar (object sender, EventArgs e)
{
    if (this.shooter == null)
    {
        this.shooter = nud2;
        nud1.Value = nud2.Value;
    }
    else this.shooter = null;
}

Of course, this is a crude example (for example, it assumes the value of both controls is always changing. Adapt to your situation.

Just use a boolean guard in the class to check whether you are inside an update method. While you are updating, all future events fired from the NUDs will be ignored.

private boolean updating = false; // Class level variable

void event_handler(...) // The function hooked up to the ValueChanged event
{
    if( !updating )
    {
        updating = true;
        // Do your calculations and update the NUDs
        updating = false;
    }        
}

I would recommend that you use data binding and bind to an object which serves as your model. Your model then is where the logic goes that alters the other value based on changing of a property. The model also raises IPropertyChanged / IPropertyChanging events, which the UI will pick up on. Not only will this prevent the issue you describe, it also keeps this business logic outside of your UI layer should you move to something else (say from WinForms to WPF, or Asp.Net MVC).

I like Andy's response about going with an MVC pattern, but if that's too radical of a change for this specific situation, you should set the values only if the current value is different than the value being assigned. That would prevent the ValueChanged event from firing again and stop the infinite loop the first time recursion happens.

// Inside your value changed handler for Control2,
// instead of directly setting the value of Control1, do this:
if(Control1.Value != valueBeingSet)
{
    Control1.Value = valueBeingSet;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM