I don't know how well I can explain this, but I'll give it a shot.
I created my own navigation class recently. It consists of a form, a grid, a navigation button group, and a container.
The grid is for record navigation. I've seen classes that just use First/Prev/Next/Last buttons and I find them cumbersome to use. I find grids to be MUCH more useful and intuitive for the user.
The nav button group contains buttons for First/Prev/Next/Last as well as New, Save/Edit, and Revert/Exit. (Save and Edit are the same button, as are Revert and Exit). I created this button group as its own self-contained class and later combined it with the form and other controls. Almost ALL of the functionality is contained in the "Navbuttons" class. It has the following properties:
[tt]
ControlSource (Character) (the name of the table)
addmode (Logical)
editmode (Logical)
modified (Logical)
SaveRec (Numeric)
[/tt]
Only ControlSource is Public. The other 4 are all Protected properties. There is no reason to expose these to any implementation.
It also has methods for each button:
[tt]
DoFirst
DoPrev
DoNext
DoLast
DoNew
DoSave
DoRevert
[/tt]
The CLICK event for each button simply calls the appropriate method in the parent. For example, on the "First" button the code is:
[tt]
THIS.PARENT.DoFirst()
[/tt]
There are also a few other stand-alone methods:
[tt]
GetMode: Returns 0 (not editing), 1 (Editing), or 2 (Adding New Record)
GetModified: Returns .T. (Record has been modified) or .F.
SetModified: Marks the record as Modified
[/tt]
The code in DoSave() does one of two things depending on the current mode: either it activates Edit mode or it Saves the record. If GetMode() returns 1 or 2, it makes a call to the form's ValidateRecord() method. If that returns .T., it issues TableUpdate() and sets the mode back to 0 (AddMode/EditMode both .F.)
The code in DoRevert() also has two functions: if GetMode() returns 1/2, it issues TableRevert() and sets the mode back to 0. (If GetModified returns .T., it asks the user to verify the cancel first). If GetMode() returns 0, it issues "Thisform.Release()"
The rest is handled in Refresh() methods. In the Grid Refresh() method, it sets its Enabled property to .T. if GetMode() returns 0, .F. if >0. The NavButtons class enables/disables its own buttons and the caption for the Edit/Save and Revert/Exit buttons based on this as well.
That leaves the Container. This is where you place all of your field controls. They should all be bound directly to the table fields since we're using Buffering. The Container's Refresh() method needs to handle enable/disable of the fields inside it based on the return value of GetMode().
I hope I explained this well enough. I have been using this class for the last few months now and it works very well for me. Let me know what you think!
Ian