Problems saving dialog data in OnOK

Viewed 254

Has anyone found a good way to save dialog data to a database in CMyDialog::OnOK?

void CMyDialog::OnOK()
{

    // If I save my data here, I don't know if DoDataExchange()
    // found validation errors.

    CDialog::OnOK();

    // If I save my data here, EndDialog() has already been called

}

Looking for ideas on how best to structure this. I know the norm is to have the caller save the data as needed but I don't want the dialog to close if I encounter an error saving the data to the database.

It seems like a good solution would be if CDialog::UpdateData() were virtual, but it is not.

3 Answers

Why not just use UpdateData?

The return value:

Nonzero if the operation is successful; otherwise 0. If bSaveAndValidate is TRUE, then a return value of nonzero means that the data is successfully validated.

So:

void CMyDialog::OnOK()
{
    if(!UpdateData(TRUE))
    {
        // There was some error with the validation procedure so don't end the dialog.
        return; // Suppress closing dialog
    }

    // OK to save data
    if(!SaveDataToDatabase())
    {
        // Some error
        return;
    }

    // Data validated Ok and was saved to DB OK, so close
    EndDialog(IDOK);
}

Unless I miss understand your question.

So, it seems clear MFC wasn't designed to work this way.

But the simplest solution I found was to modify DoDataExchange() as follows:

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);

    // DDX and DDV calls go here

    if (pDX->m_bSaveAndValidate)
    {
        if (!SaveData())
            pDX->Fail();
    }
}

The code above relies on SaveData() displaying an error message and returning false if it encounters any errors.

The result is that the regular validation is performed before I attempt to save my data. And, if the code that saves the data fails, I can still prevent the dialog box from closing via the same technique that the MFC validation methods use. (Namely, by calling pDX->Fail()).

In your comment you say this:

// If I save my data here, EndDialog() has already been called

All that means is that the HWND named m_hWnd has been closed and all the child controls with it. The window is dead, but not your instance of your CVehicleDlg. The member variables associated with the data exchange will have the values from the controls transferred to them. You should be good to go for saving.

Another approach would be to catch OnDestroy in your class instead of OnOK. That way, you get the default processing of OnOk to do the data validation. The window wouldn't be destroyed unless the data validation failed. You'll have to special case OnCancel to set some flag to "not save" when your dialog is destroyed.

Related