More Reasons
Another reason to avoid UpdateData is that UpdateData restores
all the state. This means you have to remember to save that state!
I found this the greatest problem I had in managing the use of UpdateData
before I figured out that it was simply a Bad Idea. You have to make sure, every
time a change is made, that you copy all the values out of the controls,
via UpdateData, so that if you want to make another change and restore
the values you have the correct set, not some mix of some previous values
and current values. This drove me crazy. It will probably drive you crazy, too.
In addition, if you call UpdateData, it snaps values from memory into
all of your edit controls. This will immediately cause a set of OnChange
(WM_COMMAND/EN_CHANGE) notifications, as each edit control is returned.
Now assume that there is some issue about consistency checking, such that modifying
control A affects the value in control B. But if you do UpdateData, you
have to deal with the fact that this flurry of events may happen in an order
other than the expected order from a user, and you have to make all sorts of
provisions to deal with it, such as always setting a flag that indicates if the
change should be reacted to or not.
Overall, I found that the three programs I wrote using UpdateData were
harder to write, harder to debug, and much harder to maintain, than any program
before or since in which I did not make any use of UpdateData. To me,
ease of maintenance is one of the most important concerns. Low cost of development
is also important.
The correct way, I have found, is to use control variables.
If you don't understand what a control variable is, click the hyperlink to read
my essay on them.
So how do you get the values of the controls while the dialog is active? Just
use the control variable to access the control! For example, to determine if
the OK button should be enabled, and it can only be enabled if the text
value is nonblank you can write:
CString s;
c_Text.GetWindowText(s);
s.TrimLeft();
c_OK.EnableWindow(s.GetLength() != 0);
Far easier than having to remember how to call UpdateData (is it
TRUE or FALSE for the argument?) and avoids the danger of messing
over the OK/Cancel behavior.
Where do you write the above code? Well, that's another
essay!
OK, I'll relent, just a bit, and tell you another reason to not use UpdateData,
which is the only reason I have found to use UpdateData (keep reading,
that's not a typo that makes the sentence look contradictory!) I have a client
who is offended by the situation where you have made some changes in a dialog,
gotten confused, and had to click Cancel to get out of the dialog, only
to immediately re-enter it to start over. He insisted that every dialog in his
product have a Reset button that reset the dialog to its original state.
If you avoid UpdateData this becomes easy: you use UpdateData.
What I mean is, if you avoid gratuitous, pointless, useless, UpdateData
calls (that is, in almost every dialog I can think of, any call on UpdateData),
then the original information is left intact, and a single UpdateData
call will restore all the original values. But note that the only use
of UpdateData is to load the controls with the original input values,
and this will not work if you have used it to grab the values back at intermediate
points; in this case, you have destroyed the input state. Actually, I like his
style, and so, like most dogmatists, I have to say "but there is an exception".
Thus far, it is the only exception I've found for non-database applications (see
Doug Harrison's comments, which follow below). Since I have written, literally,
hundreds of dialogs in the last five years or so, and after the first three applications
have never called UpdateData, with the one exception of resetting
all of the state to the original input state, I cannot get terribly excited about
any claims that this call is the right way to do general dialogs. Or that an
explicit call of UpdateData even has any place in them, other than the
reset case.