You should not rely on the order of events unless the events are specified as occurring in a specific order (such as BeginSomething, EndSomething). The ordering of events is an implementation detail.
As far as defaulting invalid values you can handle that in the ValueChanged event handler. You should not get in an infinite loop provided that the new value is valid. Take this sample code:
ValueChanged handler (E1)
{
if not valid
Value = default
}
SelectedValueChanged handler (or some other event that is also raised at the same time) (E2)
{
if not valid
Value = default
}
Now suppose that E1 occurs first. You detect and invalid value so you reset it. E1 will be raised again but this time it'll be valid so it does nothing. E2 is then raised (for the default value) and also sees that it is valid and does nothing.
Finally E2 occurs for the original value. If you determine the current value using the control's property then it'll determine that the value is valid and do nothing. Now if instead you are using the event arguments to determine the value then you'll determine that it is invalid and reset it. This causes E1 to be raised (doing nothing since it is valid) and then E2 (doing nothing since it is invalid). Thus it might raise extraneous events but it'll work.
Now if you switch it such that E2 occurs first then the same scenario occurs except E2 occurs followed by E1. However there are cases where you don't want a reentrant event. In this case a simple boolean flag set when you enter the event and cleared when you leave it can avoid reentrancy.
private bool bInValueChanged;
ValueChanged handler
{
if (!bInValueChanged)
{
try
{
bInValueChanged = true;
...
} finally
{
bInValueChanged = false;
};
}
}
I'd only use this approach if absolutely necessary as it adds to overhead. Also notice that no thread safety is done. That is because Win controls must be called on the UI thread and therefore are implicitly thread-safe.
Michael Taylor - 9/1/06