Reputation: 8161
I have a form with two text fields, A
and B
that are supposed to behave in the following way:
A
should set B.Text = f(A.Text)
B
should set A.Text = g(B.Text)
...for some arbitrary and potentially unrelated functions f
and g
.
The problem I'm facing is that the naive implementation of simply throwing the above code into each field's handler will create an infinite loop as A
's handler will update B
's value and call B
's handler, which will update A
, etc.
What would be the correct (and preferably thread-safe) way to handle this? Either somehow determining whether a change was done manually or programmatically, somehow suppressing events firing when changing the value, or some other way.
Upvotes: 2
Views: 1775
Reputation: 112324
Use a flag to signal that you are doing changes
private bool updating;
private void A_TextChanged(object sender, EventArgs e)
{
if (!updating) {
updating = true;
B.Text = f(A.Text);
updating = false;
}
}
private void B_TextChanged(object sender, EventArgs e)
{
if (!updating) {
updating = true;
A.Text = g(B.Text);
updating = false;
}
}
You don't have to care about thread-safety as this all happens in the unique UI-thread. UI events never create new threads; i.e. an event (click, text changed, etc.) never interrupts another one!
If you want to be sure that the flag is reset, you can use the try-finally statement. The finally block is ensured to run, even if an exception should occur within the try block (unless the application is terminated unexpectedly).
if (!updating) {
updating = true;
try {
A.Text = f(B.Text);
} finally {
updating = false;
}
}
Upvotes: 4
Reputation: 2673
I assume you're using TextChanged event, try this then:
private bool callB=true;
private bool callA=false;
private void A_Click(object sender, System.EventArgs e)
{
callB=true;
callA=false;
}
private void B_Click(object sender, System.EventArgs e)
{
callB=false;
callA=true;
}
private void A_textchanged(object sender, RoutedEventArgs e)
{
if(callB)
B.text=f(A.text);
}
private void B_textchanged(object sender, RoutedEventArgs e)
{
if(callA)
A.text=g(B.text);
}
Anyway, a better way to just edit A when the user is finished with B(finished whatever he wanted to write in it), that's because if expression will be evaluated at every character the user inputs.
By the way, changing a text while the user writes might be surprising to him, so better to avoid textchanged event in this case.
Upvotes: 1