Reputation: 5176
I am developing a c# winforms application. The underlying model has, among other things, a StartTime and an EndTime DateTime property, with the restriction, that the StartTime must come before the EndTime. To give the user the ability to change these properties, I fill two comboboxes with sample values to choose from, and hook each combobox up, so that selecting another value will change the corresponding property in the model.
The problem with this approach is that it allows the user to try to select an illegal value. Ideally, I would like it that when a user selects a certain StartTime value, the possible EndTime values are capped, so that it is not possible to select EndTime values earlier than that. One way to achieve this would be to fill the end combobox with the new legal values, and then select what was there previously. This would require that my SelectedIndexChanged event handler was temporarily shut off, since otherwise reselecting the EndTime would cause an infinite loop, alternating between filling/reselecting the StartTime and the EndTime comboboxes, respectively.
Another solution would to keep all the sample values, and then revert any illegal changes the user tries to make, but the fact that the user can try to select illegal values doesn't appeal to me. I am not fond of having to disable an event handler temporarily, since it doesn't seem clean, but I cannot see any better solutions. Do you have any suggestions or improvements?
Upvotes: 0
Views: 327
Reputation: 15813
When a combobox selection is changed, do this:
Upvotes: 1
Reputation: 62246
One time you open your form you:
boolean
variable bool SilentInvoke = false;
SelectedIndexChanged
for Start and End UI controls.In beginning of every selectedindex changed event have code more or less like this:
if( SilentInvoke)
{
SilentInvoke=false;
return;
}
User changes StartDate, enable EndDate.
SilentInvoke=true;
There is always a possibility that user goes back and changes StartDate again, but you have to have somewhere validation method that validates the data before final request.
First you give a user kind of guide ( start enabled, end disabled), after leave user free to decide and make validation before actual request.
Upvotes: 1
Reputation: 6882
I would add a class (some would call it "ModelView") designed specifically for your UI scenario. It is sort of a proxy between data model and UI. The purpose of the proxy is to maintain invariant (startDate < endDate) during editing deferring changes to the model unti editing is done. At that moment changes are applied to the underlying data object.
class MyDataObjectProxy: IPropertyChangedNotification
{
MyDataObjectProxy(MyDataObject model)
{
_model = model;
_editedStartDate = model.StartDate;
_editedEndDate = model.EndDate;
}
MyDataObject _model;
public DateTime StartDate
{
get
{
return Math.Min(editedStartDate, editedEndDate);
}
set
{
_editedStartDate = value;
RaisePropertyChanged("StartDate");
RaisePropertyChanged("EndDate");
}
}
public DateTime EndDate
{
get
{
return Math.Max(editedStartDate, editedEndDate);
}
set
{
_editedEndDate = value;
RaisePropertyChanged("StartDate");
RaisePropertyChanged("EndDate");
}
}
DateTime _editedStartDate;
DateTime _editedEndDate;
public void ApplyChanges()
{
DateTime start = StartDate;
DateTime end = EndDate;
_data.StartDate = start;
_data.EndDate = end;
}
Upvotes: 1