UpdateControls - ugly, but necessary?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

This must be a common probem for GUI designers, but one which I'm not sure of
the conventional wisdom.

I have a number of controls which are enabled/disabled according to the
states of other controls.

Do I...

1. Do all the enabling/disabling on the fly, in the handlers for the
controls which they depend on?
2. Create a method called UpdateControls, which does all the processing in
one place, and invoke it whenever the state of the form changes?

UpdateControls is less efficient, because it means that all state-dependant
controls are reviewed every time, but it is safer, because it keeps all the
logic in one place.

Is there a better way, or should I just learn to love UpdateControls?
 
Have a Google for 'state machine' or 'finite state machine'.

This is an excellent way to coherently manage application state. I'm trying
to think where the best description of the FSM is, I think it might have
been Martin Fowler's 'Patterns of Enterprise Architecture'.

--
Regards,

Tim Haughton

Agitek
http://agitek.co.uk
http://blogitek.com/timhaughton
 
Tim said:
Have a Google for 'state machine' or 'finite state machine'.

This is an excellent way to coherently manage application state. I'm trying
to think where the best description of the FSM is, I think it might have
been Martin Fowler's 'Patterns of Enterprise Architecture'.

But if I understand the OP correctly, he means things like "If I click
this radio button, suddenly this group of controls will be enabled,
while textBox1 gets a predefined value of Howdy There. The exception
being that the user has already created at least one entry in listBox2,
in which case textBox1 will say Goodbye All and of the group of
controls, one won't be visible at all. ..."

I'm obviously exaggerating, but this kind of scenario is often given in
complex forms, and writing a state machine for it might mean to create a
few hundred different states - not the tool of choice here, I think.

Don't get me wrong, I like state machines and for more global things
like "application state" they are often great tools, but GUI state is
often for too complex and volatile for them. IMHO, of course.



Oliver Sturm
 
Oliver Sturm said:
But if I understand the OP correctly, he means things like "If I click
this radio button, suddenly this group of controls will be enabled,
while textBox1 gets a predefined value of Howdy There. The exception
being that the user has already created at least one entry in listBox2,
in which case textBox1 will say Goodbye All and of the group of
controls, one won't be visible at all. ..."

After re-reading the OP's post...

Sounds like a state machine to me. It prevents nasty tangling of controls,
and keeps GUI state management in 1 place. It's also a lot easier to unit
test GUI state in this way. Someone wrote a great article recently on it,
can't find it for toffee, there's a good one at MSDN...
 
Javaman59 said:
Do I...

1. Do all the enabling/disabling on the fly, in the handlers for the
controls which they depend on?
2. Create a method called UpdateControls, which does all the processing in
one place, and invoke it whenever the state of the form changes?

UpdateControls is less efficient, because it means that all state-dependant
controls are reviewed every time, but it is safer, because it keeps all the
logic in one place.

Is there a better way, or should I just learn to love UpdateControls?

Well, usually I use an approach similar to your UpdateControls. It's
possible to code it in a way that makes it quite efficient, by
evaluating current states and only changing what's necessary. I think
that it is certainly a much cleaner solution than distributing the
update code over all the event handlers.

Another approach I have sometimes used is data binding. Of course it's
possible that you have your data organized in a way that lets you use
data binding directly - in this case, don't forget it's possible to bind
the Enabled property just like you can bind the Text property or others.

If you can't use a data class directly, you can use a "form state"
class, like this:

Assuming you have a form with a CheckBox and a TextBox. You want the
TextBox to be enabled only when the CheckBox is checked. Create a form
state class like this:

public class FormState {
private bool isChecked = true;
public bool IsChecked {
get { return isChecked; }
set { isChecked = value; }
}
}

Then, after the InitializeComponent call, have some lines similar to these:

formState = new FormState( );
checkBox1.DataBindings.DefaultDataSourceUpdateMode =
DataSourceUpdateMode.OnPropertyChanged;
checkBox1.DataBindings.Add("Checked", formState, "IsChecked");
textBox1.DataBindings.Add("Enabled", formState, "IsChecked");

The advantage with this approach is that it's automatic, and that you
have the form state class which lets you evaluate the final options
selection with the least possible overhead. The approach doesn't have
the inefficiency of the UpdateControls method, but you don't need to
write so much distributed code to support it.

Note: I just had a look and found that the DataSourceUpdateMode is only
supported in .NET 2, which I had forgotten :-) It's necessary to set
this (at least for the single data bindings), or the Enabled property
won't switch properly. I don't remember exactly, but I think that .NET 1
wasn't able to update immediately on property change, so this may not
work in .NET 1.



Oliver Sturm
 
Tim said:
Sounds like a state machine to me. It prevents nasty tangling of controls,
and keeps GUI state management in 1 place. It's also a lot easier to unit
test GUI state in this way. Someone wrote a great article recently on it,
can't find it for toffee, there's a good one at MSDN...

You got me wrong, I think. I wasn't saying that this doesn't sound like
a state machine, in essence. I was saying that a complex form like I
have in mind would result in a state machine of enormous complexity and
that I wouldn't like to write such a beast for every form I create.
Forms often don't have just one state, but many at the same time.

I second the notion that writing a complete state machine for every
complex form would probably be the noble thing to, and probably very
easy to debug and everything. If only someone was paying for the
enormous amount of time it would take.

Are you saying you do actually create such a state machine for your
forms? Are you talking from your experience, and saying that this is a
good thing to do? Don't get me wrong, I'm really asking here - I'd like
to reconsider the idea if someone tells me that I can save time by doing
this.


Oliver Sturm
 
Oliver said:
I second the notion that writing a complete state machine for every
complex form would probably be the noble thing to, and probably very
easy to debug and everything. If only someone was paying for the
enormous amount of time it would take.

.... that's what I understood from what you were saying, anyway. If you
had said "there's an existing generic implementation of such a state
machine system that only needs to be extended towards each specific use
case" I would have been much more eager to agree with you :-)


Oliver Sturm
 
Oliver Sturm said:
Are you saying you do actually create such a state machine for your
forms? Are you talking from your experience, and saying that this is a
good thing to do? Don't get me wrong, I'm really asking here - I'd like
to reconsider the idea if someone tells me that I can save time by doing
this.

With my pragmatic developer hat on, I don't start a form by creating a state
machine. If my code starts to smell because I'm managing complex state in
the wrong place, I'll think about whether or not I need a state machine.
Also - I loathe untestable code. It keeps me up at night. I usually take the
presence of untestable code to mean there's a wiff of a bad design smell. If
implementing an FSM makes a form more test friendly, I'll create an FSM.

In terms of time, don't just think about code time, think about how much
time you'll save by having code that can be tested by NUnit rather than
tested by hand. Think of the extra confidence you'll have in code that can
be given red light green light status.

--
Regards,

Tim Haughton

Agitek
http://agitek.co.uk
http://blogitek.com/timhaughton
 
Tim said:
With my pragmatic developer hat on, I don't start a form by creating a state
machine. If my code starts to smell because I'm managing complex state in
the wrong place, I'll think about whether or not I need a state machine.
Also - I loathe untestable code. It keeps me up at night. I usually take the
presence of untestable code to mean there's a wiff of a bad design smell. If
implementing an FSM makes a form more test friendly, I'll create an FSM.

In terms of time, don't just think about code time, think about how much
time you'll save by having code that can be tested by NUnit rather than
tested by hand. Think of the extra confidence you'll have in code that can
be given red light green light status.

Okay, no more discussion here. Under the circumstances you describe, I
would certainly be looking for a solution, too, which may of course be a
state machine.



Oliver Sturm
 
Thanks Tim and Oliver,

Your discussion took me out of my depth, I must admit, so I just had to
leave you to it.
But if I understand the OP correctly, he means things like "If I click
this radio button, suddenly this group of controls will be enabled,
while textBox1 gets a predefined value of Howdy There. The exception
being that the user has already created at least one entry in listBox2,
in which case textBox1 will say Goodbye All and of the group of
controls, one won't be visible at all. ..."

Yes, that's exactly the sort of thing I am talking about. The rest of this
discussion confused me, as I've never seen this sort of thing as an FSM, and
still don't.

My queston relates to where to keep the logic for updating the controls you
describe. I think Oliver answered this question in his other post.
 
Javaman59 said:
The rest of this
discussion confused me, as I've never seen this sort of thing as an FSM, and
still don't.

I still think you'll do fine without an FSM in most cases. It can't
hurt, though, to get some organisation into the way you deal with state
changes, and that's what the data binding approach I suggested in the
other post manages nicely, while still being easily applicable.

In the end, I think that state management on a form level is not one of
the things that will make a huge difference to your application
structure overall. It's you, probably, who has to maintain the
structures you create, so the best thing is to go with an approach you
thoroughly understand.



Oliver Sturm
 
Back
Top