The EX31B example is an "add-change-delete" application that's different from the Access model. The user must explicitly add, update, and delete records. Even if you prefer the Access-style behavior, you can learn a lot about the CRecordView class by going through the steps in the EX31B example.
Here are the steps for building the EX31B example:


When you're finished adding variable names for each edit box, you'll see a screen like the one shown here.
| Menu Command | Command ID | Command Handler | Update Command UI Handler |
| Add Record | ID_RECORD_ADD | OnRecordAdd | |
| Clear Fields | ID_RECORD_CLEARFIELDS | OnRecordClearfields | |
| Delete Record | ID_RECORD_DELETE | OnRecordDelete | OnUpdateRecordDelete |
| Update Record | ID_RECORD_UPDATE | OnRecordUpdate | OnUpdateRecordUpdate |
BOOL CEx31bView::OnMove(UINT nIDMoveCommand)
{
switch (nIDMoveCommand)
{
case ID_RECORD_PREV:
m_pSet->MovePrev();
if (!m_pSet->IsBOF())
break;
case ID_RECORD_FIRST:
m_pSet->MoveFirst();
break;
case ID_RECORD_NEXT:
m_pSet->MoveNext();
if (!m_pSet->IsEOF())
break;
if (!m_pSet->CanScroll()) {
// Clear screen since we're sitting on EOF
m_pSet->SetFieldNull(NULL);
break;
}
case ID_RECORD_LAST:
m_pSet->MoveLast();
break;
default:
// unexpected case value
ASSERT(FALSE);
}
// Show results of Move operation
UpdateData(FALSE);
return TRUE;
}
Also, add the declaration for this overridden function to the ex31bView.h header file.
If you have a sorted recordset (or if your ODBC driver doesn't put added records in the recordset), you should call CRecordset::Requery to completely regenerate the recordset. In that case, there's no convenient way to position the cursor on the newly added record, and that's a basic problem with SQL.
Add the following boldface code:
void CEx31bView::OnRecordAdd()
{
m_pSet->AddNew();
UpdateData(TRUE);
if (m_pSet->CanUpdate()) {
m_pSet->Update();
}
if (!m_pSet->IsEOF()) {
m_pSet->MoveLast();
}
m_pSet->Requery(); // for sorted sets
UpdateData(FALSE);
}
void CEx31bView::OnRecordClearfields()
{
m_pSet->SetFieldNull(NULL);
UpdateData(FALSE);
}
void CEx31bView::OnRecordDelete()
{
CRecordsetStatus status;
try {
m_pSet->Delete();
}
catch(CDBException* e) {
AfxMessageBox(e->m_strError);
e->Delete();
m_pSet->MoveFirst(); // lost our place!
UpdateData(FALSE);
return;
}
m_pSet->GetStatus(status);
if (status.m_lCurrentRecord == 0) {
// We deleted last of 2 records
m_pSet->MoveFirst();
}
else {
m_pSet->MoveNext();
}
UpdateData(FALSE);
}
void CEx31bView::OnUpdateRecordDelete(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_pSet->IsEOF());
}
void CEx31bView::OnRecordUpdate()
{
m_pSet->Edit();
UpdateData(TRUE);
if (m_pSet->CanUpdate()) {
m_pSet->Update();
}
// should requery if key field changed
}
void CEx31bView::OnUpdateRecordUpdate(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!m_pSet->IsEOF());
}