|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Demo project
Message displayed when exiting and there are unsaved data changes Contents
IntroductionThis library contains the code needed to add changed data protection to your forms in which the user can make changes to information. The intent is to:
When the user is queried about saving changes, the user is given the options to save the data at that point (and then continue to exit), not save the data (just exit), or cancel exiting the form. Note: add the code for the Code is available in a package file for Double Text users, as well as in a demo project for non-Double Text users. BackgroundI've been adding the Keep Changed Data code to my projects since I can't remember when. It probably goes back at least to VB 3. Now, the code has been updated to VB.NET and, with this Double Text library, I will continue to add data protection to my projects consistently and quickly. Double Text UsersLibrary OverviewThe Keep Changed Data (KCD) library consists of seven source files (.DbC) and an overview (.DbO). The KCD source files generate fully commented code that is ready to compile.
Unwrapping The Library
The library is ready to go. Repeat the code per the following instructions whenever you need to add data protection to a project. (If you don't like the way I've set up the source files, change them in the edit window.) Using The LibraryRepeating The KeepChangedData FunctionThe
The source code is now on the clipboard. If you would like to review the code, press F4. After the function code has been repeated, add it to your project.
Protecting Changes To Data In A FormThese steps are done for each form in your project in which information can be changed by the user. It is best if you add this code to each form after the form has been otherwise completed. Add And Initialize FlagsWhen a form, in which data can be entered and/or changed, loads, one or more controls may need to be initialized with current or static data. This loading of current and static data will turn on the flag that keeps track of when data has been changed. It is important, therefore, to ensure that the data changed flag is turned off after the form is done loading and all initialization of controls is completed. I use another flag, that keeps track of when a form is loading, to ensure that the data changed flag is turned off before the user can begin making changes. If this initialization of the data changed flag is not done correctly, the user will be asked about saving changes even when no changes were made.
Any code that is needed to initialize data in any controls is placed either in the form load event after the form loading flag is turned on, or in the form activated event before the data changed flag is turned off. The demo project has examples of both. Set Data Changed Flag In Each Changeable ControlThe data changed flag must be turned on in all control events that are fired when the information in the control is changed. This is normally a control's text changed or click related event depending on the control type. The appropriate event in which to turn on the data changed flag can usually be identified by double clicking on the control in the form design view. The event that is opened, or added in response to the double click on the control, should be where you want to turn on the data changed flag. The combo box is an exception. When you double click on a combo box in a form design view, the
Reset Data Changed Flag When Data SavedThe user, of course, should be able to save all data changes whenever he/she chooses. When data is saved, it is important to turn off the data changed flag so that the user is not bothered, when exiting a form, with a question about saving changes when there are no pending changes that haven't been saved.
Test Data Change Flag At ClosingThe last step is to test for unsaved changes when the user tries to exit the form.
After placing this code, you must add the code to be executed when the user chooses to save the changes. This additional code is dependent on how you write the procedure that does the saving. There is sample code in the source text that illustrates one way to handle this situation. All of the above instructions for using the library are in the library overview. Click on the Float button in the Double Text main window whenever you need a refresher. (If you change any of the source files, don't forget to reflect those changes in the overview.) Non-Double Text UsersDemo Project SummaryDownload and unzip the demo project. Open the solution in Visual Studio. When you need this code, use whichever tool you prefer to make a copy of the appropriate code, and then make any needed modifications. Add the You might want to find and change the following, either before or after you paste the code into your project.
KeepChangedData Function CodeAdd this function to a project right after you start the project. Place the function in a module for global scope. #Region " KeepChangedData function "
Public Function KeepChangedData(ByVal callingForm As Form, _
ByVal dataChanged As Boolean, _
Optional ByVal altText As _
String = Nothing) As Integer
'-----------------------------------------------------------
' Query the user as to whether or not
' the data changes made in a form are to be
' saved or discarded, or if the
' anticipated action is to be cancelled
' Pass: callingForm The form calling
this function
' dataChanged Flag indicating whether
or not any data
' changes have been made
' altText Optional question to be
displayed other than
' "Save Changes?"
' Return: 0 = Keep changed data
' 1 = Do not keep changed data
' 2 = Cancel
'-----------------------------------------------------------
' Date Developer Code Change
' ---------- -------------------- --------------------------
' 12/17/2005 G Gilbert Original code
'-----------------------------------------------------------
'-----------------------------------------------------------
' Local Constant/Variable Declarations
'-----------------------------------------------------------
Dim QuestionText As String
Dim Reply As Integer
Const QMark As String = "?"
'-----------------------------------------------------------
' Determine what the question text is to be
'-----------------------------------------------------------
If altText = Nothing Then
QuestionText = "Save changes" & QMark
Else
QuestionText = altText
'** Add a question mark, if needed
If QuestionText.Substring(QuestionText.Length - 1) _
<> QMark Then
QuestionText &= QMark
End If
End If
'-----------------------------------------------------------
' Default to "do not keep changed data"
' (for those cases where no changes were
' made)
'-----------------------------------------------------------
Reply = 1
'-----------------------------------------------------------
' If data has changed, ensure the form
' is active and not minimized. Then query
' the user as to what to do with the changed data.
'-----------------------------------------------------------
If dataChanged Then
With callingForm
If .WindowState = FormWindowState.Minimized Then
.WindowState = FormWindowState.Normal
End If
.Focus()
End With
Select Case MessageBox.Show(QuestionText, _
"Data Changed", _
MessageBoxButtons.YesNoCancel)
Case DialogResult.Yes : Reply = 0
Case DialogResult.Cancel : Reply = 2
End Select
End If
'-----------------------------------------------------------
' Return user's selection
'-----------------------------------------------------------
Return Reply
End Function
#End Region
Code Needed For Each FormThe code below is added to each form that contains controls in which the user can make changes to data. Flag DeclarationsPlace this code in the form's declarations section: Private _fbLoadingForm As Boolean
Private _fbDataChanged As Boolean
Initialize Form Loading FlagPlace this code at the beginning of the form load event before any other code: '------------------------------------------------------
' Turn on the flag that indicates the form is loading
'------------------------------------------------------
_fbLoadingForm = True
Initialize Data Changed FlagPlace this code at the end of the form activate event after all other code: '---------------------------------------
' Initialize the data changed flag
' and turn off the form loading flag
'---------------------------------------
If _fbLoadingForm Then
_fbDataChanged = False
_fbLoadingForm = False
End If
Turn On Data Changed FlagPlace this code in the appropriate event of all controls on the form that can be changed by the user. The appropriate event is that event that is fired whenever the information contained in the control is changed. '--------------------------------
' Turn on the data changed flag
'--------------------------------
_fbDataChanged = True
Turn Off Data Changed FlagPlace this code in the function that saves the data on the form after the save has been successfully completed. '--------------------------------
' Turn off the data changed flag
'--------------------------------
_fbDataChanged = False
Test For ChangesPlace this code in the form's '-------------------------------------------------
' If there are pending changes, see if
' the user wants to discard or save them
' Return: 0 = Save changed data
' 1 = Do not save changed data
' 2 = Cancel exiting form
'-------------------------------------------------
Select Case KeepChangedData(Me, _fbDataChanged)
Case 0 ' Keep changed data
'
' Code to execute when the data
' is to be saved. For example, assuming
' you have a function named
' DataSavedOK that returns True or False to
' indicate whether or not data
' has been saved successfully, the code
' for this case could be as follows.
'
' If Not DataSavedOK Then
' e.Cancel = True
' End If
'
Case 1 ' Do not keep the changed data
'** Nothing to do ... fall through
Case 2 ' Cancel exiting the form
e.Cancel = True
End Select
Testing Your CodeA very important aspect of data protection in a form is that the protection works regardless of how a user elects to exit a form. This means, the data protection test has to be made whether the user clicks an Exit button, clicks Close in the form's control box menu, clicks the form's close button, or presses Alt^F4. Testing all of the exit paths from a form is essential to ensuring the data protection scheme is solid. Testing a form's data protection code is lengthy, but, very necessary. Data protection code is worthless if it contains holes. Testing, therefore, means making sure that every control that can be changed is protected, and that the protection works regardless of how the user elects to exit the form. Here're the minimal steps for testing your data protection code:
ConclusionLosing data, or changes to data is very frustrating to users. Nothing will turn a user against an application faster than having spent time entering or modifying data only to have all the work lost because the user exited before clicking Save. Even the most intuitive, user friendly design will not salve the pain of having to do a lot of work over again. It is, therefore, imperative, in my opinion, that software developers incorporate air tight data protection into all of their projects. This is a large step towards making applications fault tolerant. Licensing And Limitation Of LiabilityYou may use the Double Text library and all code offered in this article any way you choose without restriction. Under no circumstances, and under no legal theory, tort, contract, or otherwise, will George Gilbert (hereafter referred to as "software author") or his licensors, be liable to the user of the Double Text library and all code offered in this article (hereafter referred to collectively as "article code") for any damages, including any lost profits, lost data, or other indirect, special, incidental, or consequential damages, arising out of the use or inability to use the article code, and data or information supplied, even if the software author, his licensors or authorized dealer have been advised of the possibility of such damages, or for any claim by any other party.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||