Public Overrides Sub NavigateData(ByVal navPosition As mmNavigate, ByVal raiseEvents As Boolean) If raiseEvents AndAlso (navPosition <> mmNavigate.Refresh) Then If Not (Me.ActiveControl Is Nothing) Then ' Make sure the current UI control value is written back to the data If TypeOf Me.ActiveControl.Parent Is mmDataGrid Then Dim grid As mmDataGrid = CType(Me.ActiveControl.Parent, mmDataGrid) grid.EndEdit(Nothing, grid.CurrentRowIndex, False) If TypeOf grid.DataSource Is DataSet Then Dim ds As DataSet = CType(grid.DataSource, DataSet) ' Determine the table name Dim TableName As String = Nothing Dim ViewName As String = Nothing Dim BizObj As mmBusinessObject = CType(mmAppDesktop.FormMgr.GetControlBizObj(grid), mmBusinessObject) If Not (BizObj Is Nothing) Then mmBindingStrategyBase.GetBindingSource(BizObj, grid.BindingSourceMember, TableName, ViewName) End If If Not mmString.Empty(TableName) Then ds.Tables(TableName).Rows(grid.CurrentRowIndex).EndEdit() Else ds.Tables(0).Rows(grid.CurrentRowIndex).EndEdit() End If Else If TypeOf grid.DataSource Is DataView Then Dim dv As DataView = CType(grid.DataSource, DataView) dv.Table.Rows(grid.CurrentRowIndex).EndEdit() End If End If Else Dim cntrl As Control = CType(Me.ActiveControl, Control) If cntrl.DataBindings.Count > 0 Then Me.BindingContext(cntrl.DataBindings(0).DataSource).EndCurrentEdit() End If End If End If Dim IgnoreIsChanged As Boolean = Me.IgnoreIsChanged ' We only want to ignore the first time here after IgnoreIsChanged is set. If Me.IgnoreIsChanged Then Me.IgnoreIsChanged = False End If ' Check for changes If Me.IsChanged() Then ' This is where we override the default behavior. If Not IgnoreIsChanged Then Dim CancelControl As Control = Me.FocusOnCancelControl Dim SaveControl As Control = Me.FocusOnSaveControl Me.FocusOnCancelControl = Nothing Me.FocusOnSaveControl = Nothing ' Ask the user if they want to save changes Dim result As DialogResult = Me.AskSaveChanges() Me.FocusOnCancelControl = CancelControl Me.FocusOnSaveControl = SaveControl If result = DialogResult.Cancel Then Return End If End If End If End If MyBase.NavigateData(navPosition, raiseEvents) End SubI found that it is still necessary to provide a way to override inappropriate calls to AskSaveChanges(). I did this by adding a protected variable to ABusinessForm in my BusinessForm.vb:
' Ignore IsChanged in NavigateData(). ' This allows us to not be prompted with AskSaveChanges in NavigateData ' when the user clicks instances of btnNew, btnDelete, or btnClose. Protected IgnoreIsChanged As Boolean = FalseIn my forms which are subclassed from ABusinessForm I set IgnoreIsChanged = True in the click method of buttons which call HookPreNavigate() where I am being prompted inappropriately, in the HookPreCancel(), and in HookPreDelete(). For instance, on a given form btnNew is an instance of mmButtonNew. Clicking this button adds a row to the primary bizobj of the form. Since my business objects have
Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click If Me.btnNew.Result Then ' Ignore the IsChanged property in ABusinessForm.NavigateData Me.IgnoreIsChanged = True ' Navigate to the new record. There should be a way around this. Me.NavigateData(mmNavigate.Last, True) End If End SubWouldn't it be better if NavigateData(), rather than calling IsChanged() to determine if the business object has any changes, would instead call something to determine if the current row has any changes? If the current row has changes and the user declines to either save or abandon changes then navigation would be disallowed. I believe this would have the desired result. And would be cleaner than my current work around.