Results 1 to 1 of 1

Thread: Changed Class (Keep track of the "dirty" status of your data).

  1. #1

    Thread Starter
    PowerPoster cafeenman's Avatar
    Join Date
    Mar 2002
    Location
    Florida
    Posts
    2,636

    Changed Class (Keep track of the "dirty" status of your data).

    Edit: I made a couple dumb errors in the Demo and fixed them. They weren't important to the point of the Demo so you don't have to download the new ZIP if you don't want to.

    cChanged Demo.zip


    This is a Changed Class I wrote and use in all my applications that can save data. The reason I wrote it is because I could use the Changed Event in any given control to do whatever but the problem is that if you have multiple ways to get to the same thing (I'll explain that next) then you start triggering a whole lot of changed events and depending on how many different systems you have on one form it can cause a lot of flickering of buttons and such if you want to use Changed to enable/disable controls.

    E.g. mnuFileSave is Disabled if nothing is changed.

    Multiple ways means maybe you have a Customer form that's a front-end to a database. You have the normal four arrow keys - First, Last, Previous, Next. When you click one of those you reposition the recordset. There's also a ComboBox on the form with a list of customer names. When you reposition, the ComboBox displays the current customer.

    But... you can also reposition the recordset by selecting a customer from the ComboBox which triggers the ComboBox again. This is a whole different problem but the way I solved it was in the Reposition Event (after prompting user to save record if applicable), Changed is first checked to see if it's disabled. If it is, the code skips out. If it's not then it Disables it and carries on. There are other ways to prevent unintentional recursive events but that's how I handled it.

    I wrote up a demo program that is attached. This is just the cChanged Class code. Ignore the debug stuff. In the sample program I just put in dummy subs to handle that so I don't have to maintain two versions of the code.

    Code:
    Option Explicit
    
    
    ' Changed Property is Default Member of this Class.
    
    
    
    ' // Events.
    
    
    Public Event Changed() ' Raises Event (Changed) when Set. Does not Fire when Changed Object is Disabled.
    
    
    ' // Events.
    
    
    
    ' // Constants, Enums and Types.
    
    
    Private Const NAME As String = "cChanged"
    
    Public Enum CHANGED_STATUS ' The Status Changed can have: Changed (Checked), Indeterminate (Grayed) or Unchanged (Unchecked).
    
      idx_ChangedStatusIsChanged = vbChecked      ' 1
      idx_ChangedStatusIsIndeterminate = vbGrayed ' 2
      idx_ChangedStatusIsUnchanged = vbUnchecked  ' 0
    
    End Enum
    
    
    ' // Constants, Enums and Types.
    
    
    
    ' // Properties.
    
    
    Private nChanged As CHANGED_STATUS            ' Manages "Dirty" status of record.
    Private fEnabled As Boolean                   ' Sets Changed Status to idx_ChangedIndeterminate when Disabled = True.  Restores previous Changed Status.  Previous Changed Status must be Changed or Unchanged.
    Private nPriorChangedStatus As CHANGED_STATUS ' Saves Changed Status immediately before Changed is Disabled.
    
    
    ' // Properties.
    
    
    Public Property Get Changed() As CHANGED_STATUS
    
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".Changed(Public Property Get)"
    
    Changed = nChanged
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Public Property Let Changed(ByVal DataChanged As CHANGED_STATUS)
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".Changed(Public Property Let)"
    
    If Not fEnabled Then GoTo CleanUp
    
    nChanged = DataChanged
    
    RaiseEvent Changed
    
    CleanUp:
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Public Function DestroyObjects() As Long
    
    ' Returns Error Code.
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".DestroyObjects(Public Function)"
    
    ' Dummy sub.
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Function
    Public Property Get Enabled() As Boolean
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".Enabled(Public Property Get)"
    
    Enabled = fEnabled
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Public Property Let Enabled(ByRef EnableChanged As Boolean)
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".Enabled(Public Property Let)"
    
    If EnableChanged = False Then ' Save current Changed Status if Changed Object is going to be disabled.
    
      SavePriorChangedStatus EnableChanged
    
    Else
    
     RestoreChangedStatus EnableChanged ' Restore Saved Changed Status if Changed Object is being Enabled.
    
    End If
    
    fEnabled = EnableChanged
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Private Property Get PriorChangedStatus() As CHANGED_STATUS
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".PriorChangedStatus(Private Property Get)"
    
    PriorChangedStatus = nPriorChangedStatus
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Private Property Let PriorChangedStatus(ByRef ChangedStatus As CHANGED_STATUS)
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".PriorChangedStatus(Private Property Let)"
    
    nPriorChangedStatus = ChangedStatus
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Property
    Private Sub RestoreChangedStatus(ByRef EnableStatusChange As Boolean)
    
    ' This Sub should only be called when Disabled is being set to False.  E.g. Changed.Disabled = False
    ' This Sub is called *Before* the actual Status of Disabled is Changed.
    ' Restores Changed Status to what it was before Changed was Disabled.
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".RestoreChangedStatus(Private Sub)"
    
    If (fEnabled = True) Or (EnableStatusChange = False) Then GoTo CleanUp
    
    nChanged = PriorChangedStatus
    
    CleanUp:
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Sub
    Private Sub SavePriorChangedStatus(ByRef EnableStatusChange As Boolean)
    
    ' This Sub should only be called when Disabled is being set to True.  E.g. Changed.Disabled = True
    ' This Sub is called *Before* the actual Status of Disabled is Changed.
    ' Current Changed Status is Saved when Changed is Disabled and Restored when Changed is Re-enabled.
    ' Changed Status is Set to idx_ChangedInderminate.
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".SavePriorChangedStatus(Private Sub)"
    
    If (fEnabled = False) Or (EnableStatusChange = True) Then GoTo CleanUp ' Changed is currently Disabled so this should already be set.
                                                                           ' Or Status is being switched to Enabled.  See RestoreChangedStatus.
                                                                  
    If nChanged <> idx_ChangedStatusIsIndeterminate Then PriorChangedStatus = nChanged ' Only save idx_ChangedStatusIsChanged or idx_ChangedStatusIsUnchanged, but not idx_ChangedStatusIsIndeterminate
    
    nChanged = idx_ChangedStatusIsIndeterminate ' Changed Status will always be idx_ChangedStatusIsIndeterminate if Changed is Disabled.
    
    CleanUp:
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Sub
    Private Sub Class_Initialize()
    
    If DebugMode = idx_Debug_On Then CallStack.Add NAME & ".Class_Initialize(Private Sub)"
    
    fEnabled = True ' On by default.  Otherwise every instance would need to enable its Changed object.
    nPriorChangedStatus = idx_ChangedStatusIsIndeterminate
    
    If DebugMode = idx_Debug_On Then CallStack.DeleteProcedureCall
    
    End Sub
    Last edited by cafeenman; Mar 27th, 2024 at 02:35 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width