Validation in OnKillfocus vs. DDV_ in DoDataExchange 
Author Message
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

If I want to do custom validation of data that is input via edit
controls in a dialog box, are there any advantages or disadvantages to
doing the validation within OnKillfocus routines for the edit controls
versus doing the validation within a custom DDV_ routine called from
DoDataExchange?  

Thanks.
Bert



Fri, 22 Oct 2004 16:42:49 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:
>If I want to do custom validation of data that is input via edit
>controls in a dialog box, are there any advantages or disadvantages to
>doing the validation within OnKillfocus routines for the edit controls
>versus doing the validation within a custom DDV_ routine called from
>DoDataExchange?  

Bert,

Validating in OnKillFocus is often problematic if you need to display
a message box indicating the error - you then end up in a vicious
loop.

It's certainly neater not to do it that way.

Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq
My address is altered to discourage junk mail.
Please post responses to the newsgroup thread,
there's no need for follow-up email copies.



Fri, 22 Oct 2004 17:57:37 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange


Quote:
> If I want to do custom validation of data that is input via
> edit controls in a dialog box, are there any advantages or
> disadvantages to doing the validation within OnKillfocus
> routines for the edit controls versus doing the validation
> within a custom DDV_ routine called from DoDataExchange?

Some say yea, some say nay.

If you validate each field in OnKillFocus you can alert the user
as soon as an invalid entry is made. This has a number of
advantages, not least that fact that the alert is more readily  
associated by the user with the particular value that caused it,
and the fact that each input control can provide its own
(possibly more meaningful) error message.

The downside is that it tempts one to employ more complex
validation strategies in which the acceptable values for one
control depend on the value already set in another control. This
can be very confusing to the user who isn't expecting any
validation to be done until he has made up his mind about all the
firelds and clicks "OK". It's also (possibly quite a lot) more
work, of course.

Joseph Newcomer has written an essay on this subject that you
should be able to download from his website (I have a link to
http://www3.pgh.net/~newcomer/mvp_tips.htm). Joe is in the
OnKillFocus school, while I generally prefer OnDataExchange for
simplicity. Whichever method you decide to use, it's important to
use the same method for all dialogs in an application or the user
will get *really* confused by the fact that some dialogs validate
each control on entry while others only validate on closing.

Cheers,
 Daniel.



Fri, 22 Oct 2004 19:24:59 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:



>> If I want to do custom validation of data that is input via
>> edit controls in a dialog box, are there any advantages or
>> disadvantages to doing the validation within OnKillfocus
>> routines for the edit controls versus doing the validation
>> within a custom DDV_ routine called from DoDataExchange?

>Some say yea, some say nay.

>If you validate each field in OnKillFocus you can alert the user
>as soon as an invalid entry is made. This has a number of
>advantages, not least that fact that the alert is more readily  
>associated by the user with the particular value that caused it,
>and the fact that each input control can provide its own
>(possibly more meaningful) error message.

This is the behavior I prefer, at least for the current application.

Quote:
>The downside is that it tempts one to employ more complex
>validation strategies in which the acceptable values for one
>control depend on the value already set in another control. This
>can be very confusing to the user who isn't expecting any
>validation to be done until he has made up his mind about all the
>firelds and clicks "OK". It's also (possibly quite a lot) more
>work, of course.

Control dependency is not a concern for the current app.

Quote:
>Joseph Newcomer has written an essay on this subject that you
>should be able to download from his website (I have a link to
>http://www3.pgh.net/~newcomer/mvp_tips.htm). Joe is in the
>OnKillFocus school, while I generally prefer OnDataExchange for
>simplicity. Whichever method you decide to use, it's important to
>use the same method for all dialogs in an application or the user
>will get *really* confused by the fact that some dialogs validate
>each control on entry while others only validate on closing.

>Cheers,
> Daniel.

Thanks, Daniel. I'm not sure I agree with Newcomer's basic premise
regarding the "expected" behavior when selecting Cancel, but the
article does give me a better understanding of the process. In any
case, for the time being I've decided to go with the DDV_ approach.
I'm experimenting with OnKillfocus routines that simply call
UpdateData(TRUE). This provides for input checking as soon as the user
tries to exit the control, but there are two undesired results: (1)
the user can't Cancel the dialog if there is invalid data in the
current field, and (2) selecting a different window (e.g., the window
of a different app) causes immediate input checking of the current
control, and display of the error message if that input is invalid. I
imagine there's a way around this by conditionally calling UpdateData,
if I can just figure out how to determine if the user is trying to set
the focus to Cancel or to another window, rather than to other
(non-Cancel) controls within the same window.

Bert



Sat, 23 Oct 2004 03:36:20 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:

>>If I want to do custom validation of data that is input via edit
>>controls in a dialog box, are there any advantages or disadvantages to
>>doing the validation within OnKillfocus routines for the edit controls
>>versus doing the validation within a custom DDV_ routine called from
>>DoDataExchange?  

>Bert,

>Validating in OnKillFocus is often problematic if you need to display
>a message box indicating the error - you then end up in a vicious
>loop.

>It's certainly neater not to do it that way.

>Dave

Thanks, Dave. I didn't notice the loop behavior in the one case that I
tried, even though I did display an error message box. Perhaps that's
because I included a SetFocus command to force the focus back to the
control with the invalid data?

Bert



Sat, 23 Oct 2004 03:37:22 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:
>Thanks, Dave. I didn't notice the loop behavior in the one case that I
>tried, even though I did display an error message box. Perhaps that's
>because I included a SetFocus command to force the focus back to the
>control with the invalid data?

I think you'll find it can arise once you've got more than 1 control
that you've validating that way.

Eg. tab from control 1 to control 2, but control 1 DDV causes a
message box, which then causes a kill focus from control 2, which then
causes its own DDV. :(

Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq
My address is altered to discourage junk mail.
Please post responses to the newsgroup thread,
there's no need for follow-up email copies.



Sat, 23 Oct 2004 04:42:00 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange


Quote:
> Thanks, Daniel. I'm not sure I agree with Newcomer's basic
> premise regarding the "expected" behavior when selecting
> Cancel, ...

There are actually two articles on Joe's site that I intended to
direct you to ... one is  "Avoiding UpdateData"
(http://www3.pgh.net/~newcomer/updatedata.htm) which you seem to
have found. The other is "A Validating Edit Control"
(http://www3.pgh.net/~newcomer/validating_edit_control.htm) which
you may not have.

Joe's point about Cancel behaviour is simply that data held by the
application should not be altered by the code of a dialog box if
the user cancels the dialog. I believe that he's quite right (on
that point, at least) and that this is an important point.

There's more than one way to ensure that a cancelled dialog
doesn't alter application data, though, and Joe argues for only
one of them.

In most MFC applications there is data stored in a model (e.g. a
CDocument-derived object) that can be altered by the user /via/
some dialog box. Typically the application created a dialog object
and *copies* data into member variables of the dialog class and
calls DoModal(). The MFC dialog code then invokes the UpdateData
method of the dialog which copies that data (again!) into the
windows control objects that make up the dialog.

If your dialog class calls UpdateData(TRUE) the member variables
will be updated from the windows controls, but that won't alter
the data in the document. When the user closes the dialog by
clicking "OK" or "cancel" the dialog will be closed and IDOK or
IDCANCEL will be returned to the application. The application
should test the return value and only copy the updated values from
the dialog box's member variables if the value returned was IDOK.
As long as the application discards the values in the dialog's
members if IDCANCEL is returned the document will not be altered
when the user cancels the dialog.

[NOTE: It's done this way because that's the way the MFC wizards
generate their code. If you hand-code the DDX statements in
DoDataExchange you can avoid copying data into member variables:

  DDX_Text( pDX, IDC_WHATEVER, GetDocument()->m_strWhatever );

(just don't expect the Class Wizard to work with codse like this).
If you do this you should certainly follow Joe's advice otherwise
the document will be updated directly by your calls to UpdateData
and those changes cannot be undone if the user later cancels the
dialog.]

I do believe that Joe is right to advise against calling
UpdateData from your own code, though. If you want/need to perform
field-by-field validation of data you should validate *only* the
field that the user has just entered - don't validate the whole
dialog every time.

Quote:
> I'm experimenting with OnKillfocus routines that simply call
> UpdateData(TRUE).

I think that is absolutely the *worst* thing you could do. It
combines all the disadvantages of UpdateData with all those of
field-by-field validation (and brings few of the benefits of
either).

Quote:
> ... but there are two undesired results: (1) the user can't
> Cancel the dialog if there is invalid data in the current
> field, ...

.. or indeed in any field. The user should *always* be able to
cancel a dialog.

Quote:
> ... and (2) selecting a different window (e.g., the window of
> a different app) causes immediate input checking of the current
> control, and display of the error message if that input is
> invalid.

That's one of the things that makes field-by-field validation
tricky. You have to check for your application losing focus, and
when you get focus back again you have to check to see whether the
same control is current as when you last had focus (and /then/
validate).

Quote:
> I imagine there's a way around this by conditionally calling
> UpdateData, if I can just figure out how to determine if the
> user is trying to set the focus to Cancel or to another window,
> rather than to other (non-Cancel) controls within the same
> window.

I'll say it again: Don't use UpdateData like this.

You can tell which control is getting the focus by looking at the
pNewWnd parameter of OnKillFocus and comparing it with the
OnCancel button (CWnd::operator== compares the m_hWnd members of
two CWnd objects, so you can do something like:

  if( (*pNewWnd)==m_btnCancel )
  {
    ...

where m_btnCancel is a CButton member variable of your dialog
class and is bound to the cancel button).

Cheers,
 Daniel.



Sat, 23 Oct 2004 19:03:44 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:

>>Thanks, Dave. I didn't notice the loop behavior in the one case that I
>>tried, even though I did display an error message box. Perhaps that's
>>because I included a SetFocus command to force the focus back to the
>>control with the invalid data?

>I think you'll find it can arise once you've got more than 1 control
>that you've validating that way.

>Eg. tab from control 1 to control 2, but control 1 DDV causes a
>message box, which then causes a kill focus from control 2, which then
>causes its own DDV. :(

OK, that makes sense. I guess I don't really understand yet everything
that happens, or at least the order that it happens, when the user
clicks on a different control or a different window, and the MS
documentation has some, shall we say, shortcomings.  

Bert



Sun, 24 Oct 2004 17:24:39 GMT  
 Validation in OnKillfocus vs. DDV_ in DoDataExchange

Quote:



>> Thanks, Daniel. I'm not sure I agree with Newcomer's basic
>> premise regarding the "expected" behavior when selecting
>> Cancel, ...

>Joe's point about Cancel behaviour is simply that data held by the
>application should not be altered by the code of a dialog box if
>the user cancels the dialog. I believe that he's quite right (on
>that point, at least) and that this is an important point.

Yes. When I said I'm not sure I agree with him, I was thinking in
terms of his assertion that the calling function should be able to
assume that the dialog data remains unchanged if the Cancel button is
selected. To me, it makes more sense to say that the dialog should be
free to do what it wants with it's data. The assumption, IMO, should
be that the calling function will retain it's own set of data and will
look to see whether Cancel or Enter was selected before deciding to
use the dialog data to update it's own data. This seems to be your
position as well, based on the rest of your discussion (snipped).

Quote:
>> I'm experimenting with OnKillfocus routines that simply call
>> UpdateData(TRUE).

>I think that is absolutely the *worst* thing you could do. It
>combines all the disadvantages of UpdateData with all those of
>field-by-field validation (and brings few of the benefits of
>either).

Yeah, I thought it would be either the best of both or the worst of
both. I just wasn't sure which until I started playing with it.

Quote:
>> ... but there are two undesired results: (1) the user can't
>> Cancel the dialog if there is invalid data in the current
>> field, ...

>.. or indeed in any field. The user should *always* be able to
>cancel a dialog.

Agreed.

Quote:
>> ... and (2) selecting a different window (e.g., the window of
>> a different app) causes immediate input checking of the current
>> control, and display of the error message if that input is
>> invalid.

>That's one of the things that makes field-by-field validation
>tricky. You have to check for your application losing focus, and
>when you get focus back again you have to check to see whether the
>same control is current as when you last had focus (and /then/
>validate).

Right.

Quote:
>You can tell which control is getting the focus by looking at the
>pNewWnd parameter of OnKillFocus and comparing it with the
>OnCancel button (CWnd::operator== compares the m_hWnd members of
>two CWnd objects, so you can do something like:

>  if( (*pNewWnd)==m_btnCancel )
>  {
>    ...

>where m_btnCancel is a CButton member variable of your dialog
>class and is bound to the cancel button).

Thanks. I'll play around with this.

Bert



Sun, 24 Oct 2004 18:02:01 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. Field Level Validation and OnKillFocus

2. DDV - dialog box data validation

3. Breaking OnKillFocus

4. INFINITE LOOP on OnSetFocus OnKillFocus????

5. OnKillFocus problem

6. CButton::OnKillfocus()

7. OnKillFocus

8. CEdit - OnKillFocus

9. OnKillFocus()

10. OnKillFocus problem

11. Validating at OnKillFocus

12. Breaking OnKillFocus

 

 
Powered by phpBB® Forum Software