Version 2.8.3 zu Test an MK und HE
This commit is contained in:
@@ -25,7 +25,8 @@ Namespace ControlCreator
|
||||
|
||||
Private newRowModified As Boolean
|
||||
Private isApplyingInheritedValue As Boolean
|
||||
|
||||
Private _FormulaColumnNames As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
|
||||
Private _isRefreshingFormula As Boolean = False ' *** NEU: Flag für Formel-Refresh ***
|
||||
Public Sub New(pLogConfig As LogConfig, pGridTables As Dictionary(Of Integer, Dictionary(Of String, RepositoryItem)))
|
||||
_LogConfig = pLogConfig
|
||||
_Logger = pLogConfig.GetLogger()
|
||||
@@ -315,7 +316,7 @@ Namespace ControlCreator
|
||||
settings.MaskExpression = "c"
|
||||
settings.Culture = oCultureInfo
|
||||
End Sub)
|
||||
riTextEdit.UseMaskAsDisplayFormat = True 'Optional
|
||||
riTextEdit.UseMaskAsDisplayFormat = True
|
||||
pGrid.RepositoryItems.Add(riTextEdit)
|
||||
|
||||
For Each oCol As GridColumn In pGridView.Columns
|
||||
@@ -327,6 +328,14 @@ Namespace ControlCreator
|
||||
Continue For
|
||||
End If
|
||||
|
||||
' Formel-Spalten dürfen kein ColumnEdit bekommen, da der RepositoryItem-Cache
|
||||
' den berechneten Wert nach RefreshRowCell überschreibt.
|
||||
Dim oFormulaExpression = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty)
|
||||
If oFormulaExpression <> String.Empty Then
|
||||
_Logger.Debug("Skipping ColumnEdit assignment for formula column [{0}] – using DisplayFormat only.", oCol.FieldName)
|
||||
Continue For
|
||||
End If
|
||||
|
||||
Dim oColumnType As String = oColumnData.Item("TYPE_COLUMN")
|
||||
|
||||
Select Case oColumnType
|
||||
@@ -337,6 +346,15 @@ Namespace ControlCreator
|
||||
Next
|
||||
End Sub
|
||||
Public Sub ConfigureViewEvents(pColumnTable As DataTable, pGridView As GridView, pControl As Windows.Forms.Control, pControlId As Integer)
|
||||
' Formel-Spalten-Namen einmalig cachen für View_ShowingEditor
|
||||
_FormulaColumnNames.Clear()
|
||||
For Each r As DataRow In pColumnTable.Rows
|
||||
Dim oExpr = ObjectEx.NotNull(r.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
|
||||
If oExpr <> String.Empty Then
|
||||
_FormulaColumnNames.Add(r.Item("SPALTENNAME").ToString())
|
||||
End If
|
||||
Next
|
||||
|
||||
AddHandler pGridView.InitNewRow, Sub(sender As Object, e As InitNewRowEventArgs)
|
||||
Try
|
||||
_Logger.Debug("Initialzing new row")
|
||||
@@ -394,30 +412,233 @@ Namespace ControlCreator
|
||||
End Sub
|
||||
|
||||
AddHandler pGridView.PopupMenuShowing, AddressOf View_PopupMenuShowing
|
||||
|
||||
AddHandler pGridView.InvalidRowException, AddressOf View_InvalidRowException
|
||||
AddHandler pGridView.ValidatingEditor, AddressOf View_ValidatingEditor
|
||||
' AddHandler pGridView.CustomColumnDisplayText, AddressOf View_CustomColumnDisplayText
|
||||
AddHandler pGridView.ShownEditor,
|
||||
Sub(sender As Object, e As EventArgs)
|
||||
Dim view As GridView = TryCast(sender, GridView)
|
||||
If view.IsNewItemRow(view.FocusedRowHandle) Then
|
||||
_Logger.Debug("Attaching Modified Handler.")
|
||||
AddHandler view.ActiveEditor.Modified, Sub()
|
||||
_Logger.Debug("Row was modified.")
|
||||
newRowModified = True
|
||||
End Sub
|
||||
End If
|
||||
|
||||
' *** KRITISCH: LIVE-REFRESH bei JEDER Eingabe (auch NewItemRow!) ***
|
||||
If view.FocusedColumn IsNot Nothing AndAlso view.ActiveEditor IsNot Nothing Then
|
||||
Dim oFocusedColumnName As String = view.FocusedColumn.FieldName
|
||||
|
||||
' Prüfen ob diese Spalte von Formel-Spalten referenziert wird
|
||||
Dim oFormulaColumnsToRefresh As New List(Of String)
|
||||
For Each oColumnData As DataRow In pColumnTable.Rows
|
||||
Dim oExpr = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
|
||||
If oExpr = String.Empty Then Continue For
|
||||
|
||||
Dim referencedColumns = GetReferencedColumnNames(oExpr)
|
||||
If referencedColumns.Any(Function(col) String.Equals(col, oFocusedColumnName, StringComparison.OrdinalIgnoreCase)) Then
|
||||
oFormulaColumnsToRefresh.Add(oColumnData.Item("SPALTENNAME").ToString())
|
||||
End If
|
||||
Next
|
||||
|
||||
If oFormulaColumnsToRefresh.Count > 0 Then
|
||||
_Logger.Debug("[FormulaRefresh] Attaching EditValueChanged handler for LIVE formula updates on column [{0}].", oFocusedColumnName)
|
||||
|
||||
' Handler für LIVE Aktualisierung während JEDER Eingabe
|
||||
AddHandler view.ActiveEditor.EditValueChanged,
|
||||
Sub(editorSender As Object, editorArgs As EventArgs)
|
||||
Try
|
||||
Dim oRowHandle As Integer = view.FocusedRowHandle
|
||||
If Not view.IsValidRowHandle(oRowHandle) Then Return
|
||||
|
||||
Dim oEditor As DevExpress.XtraEditors.BaseEdit = TryCast(editorSender, DevExpress.XtraEditors.BaseEdit)
|
||||
If oEditor Is Nothing Then Return
|
||||
|
||||
Dim isNewItemRow As Boolean = view.IsNewItemRow(oRowHandle)
|
||||
|
||||
Try
|
||||
Dim oValue As Object = oEditor.EditValue
|
||||
|
||||
If TypeOf oEditor Is DevExpress.XtraEditors.TextEdit Then
|
||||
Dim oTextEdit As DevExpress.XtraEditors.TextEdit = DirectCast(oEditor, DevExpress.XtraEditors.TextEdit)
|
||||
If oTextEdit.Properties.MaskSettings IsNot Nothing Then
|
||||
oValue = oEditor.EditValue
|
||||
End If
|
||||
End If
|
||||
|
||||
If isNewItemRow Then
|
||||
_Logger.Debug("[FormulaRefresh] EditValueChanged (NewItemRow) – setting value for [{0}] = [{1}].", oFocusedColumnName, oValue)
|
||||
|
||||
_isRefreshingFormula = True
|
||||
Try
|
||||
' Wert setzen
|
||||
view.SetRowCellValue(oRowHandle, oFocusedColumnName, If(oValue Is Nothing, DBNull.Value, oValue))
|
||||
|
||||
' *** KRITISCH: DoEvents() damit SetRowCellValue processed wird ***
|
||||
view.UpdateCurrentRow()
|
||||
|
||||
' Formel-Spalten SOFORT refreshen
|
||||
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
|
||||
Dim oGridColumn As GridColumn = view.Columns.ColumnByFieldName(oFormulaColumnName)
|
||||
If oGridColumn IsNot Nothing Then
|
||||
view.RefreshRowCell(oRowHandle, oGridColumn)
|
||||
_Logger.Debug("[FormulaRefresh] (NewItemRow) Refreshed [{0}], current value: [{1}]",
|
||||
oFormulaColumnName, view.GetRowCellValue(oRowHandle, oGridColumn))
|
||||
End If
|
||||
Next
|
||||
Finally
|
||||
_isRefreshingFormula = False
|
||||
End Try
|
||||
|
||||
Else
|
||||
' Bestehende Row
|
||||
Dim oDataRow As DataRow = view.GetDataRow(oRowHandle)
|
||||
If oDataRow IsNot Nothing Then
|
||||
_Logger.Debug("[FormulaRefresh] EditValueChanged – setting value for [{0}] in DataTable.", oFocusedColumnName)
|
||||
oDataRow.Item(oFocusedColumnName) = If(oValue Is Nothing, DBNull.Value, oValue)
|
||||
|
||||
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
|
||||
Dim oGridColumn As GridColumn = view.Columns.ColumnByFieldName(oFormulaColumnName)
|
||||
If oGridColumn IsNot Nothing Then
|
||||
view.RefreshRowCell(oRowHandle, oGridColumn)
|
||||
Dim currentValue = view.GetRowCellValue(oRowHandle, oGridColumn)
|
||||
_Logger.Debug("[FormulaRefresh] Current value for [{0}]: [{1}]", oFormulaColumnName, currentValue)
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
End If
|
||||
|
||||
Catch parseEx As Exception
|
||||
_Logger.Debug("[FormulaRefresh] Parse error during EditValueChanged: {0}", parseEx.Message)
|
||||
End Try
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
|
||||
' These handlers are all used for the custom DefaultValue functionality, additionally some code in the 'InitNewRow' event.
|
||||
' https://supportcenter.devexpress.com/ticket/details/t1035580/how-to-default-a-value-in-a-column-when-add-new-row-in-data-grid
|
||||
AddHandler pGridView.ShowingEditor, AddressOf View_ShowingEditor
|
||||
AddHandler pGridView.ShownEditor, AddressOf View_ShownEditor
|
||||
AddHandler pGridView.ValidateRow, AddressOf View_ValidateRow
|
||||
AddHandler pControl.LostFocus, AddressOf Control_LostFocus
|
||||
|
||||
AddHandler pGridView.ShowingEditor,
|
||||
Sub(sender As Object, e As CancelEventArgs)
|
||||
Try
|
||||
Dim oView As GridView = TryCast(sender, GridView)
|
||||
If oView Is Nothing Then Return
|
||||
|
||||
_Logger.Debug("Showing editor.")
|
||||
|
||||
' Formel-Spalten dürfen keinen Editor öffnen
|
||||
If oView.FocusedColumn IsNot Nothing Then
|
||||
Dim oFieldName As String = oView.FocusedColumn.FieldName
|
||||
If _FormulaColumnNames.Contains(oFieldName) Then
|
||||
_Logger.Debug("Cancelling editor – column [{0}] is a formula column.", oFieldName)
|
||||
e.Cancel = True
|
||||
Return
|
||||
End If
|
||||
End If
|
||||
|
||||
If oView.IsNewItemRow(oView.FocusedRowHandle) AndAlso Not newRowModified Then
|
||||
_Logger.Debug("Adding new row.")
|
||||
oView.AddNewRow()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
AddHandler pGridView.FocusedColumnChanged,
|
||||
Sub(sender As Object, e As FocusedColumnChangedEventArgs)
|
||||
Try
|
||||
Dim oView As GridView = TryCast(sender, GridView)
|
||||
If oView Is Nothing Then Return
|
||||
|
||||
Dim oRowHandle As Integer = oView.FocusedRowHandle
|
||||
If oView.IsNewItemRow(oRowHandle) Then Return
|
||||
If Not oView.IsValidRowHandle(oRowHandle) Then Return
|
||||
|
||||
If oView.FocusedColumn IsNot Nothing AndAlso
|
||||
_FormulaColumnNames.Contains(oView.FocusedColumn.FieldName) Then
|
||||
_Logger.Debug("[FormulaRefresh] FocusedColumnChanged – closing editor on formula column [{0}].", oView.FocusedColumn.FieldName)
|
||||
oView.CloseEditor()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
AddHandler pGridView.CellValueChanged,
|
||||
Sub(sender As Object, e As CellValueChangedEventArgs)
|
||||
' *** HandleInheritedColumnValue MUSS zuerst aufgerufen werden ***
|
||||
Try
|
||||
HandleInheritedColumnValue(TryCast(sender, GridView), pColumnTable, e)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
|
||||
' *** Formel-Refresh via CellValueChanged ist FALLBACK ***
|
||||
' (EditValueChanged macht das normalerweise schon LIVE)
|
||||
Try
|
||||
Dim oView As GridView = TryCast(sender, GridView)
|
||||
If oView Is Nothing OrElse e.Column Is Nothing Then Return
|
||||
|
||||
' Prüfen ob überhaupt eine Formel-Spalte referenziert wird
|
||||
Dim oFormulaColumnsToRefresh As New List(Of String)
|
||||
|
||||
For Each oColumnData As DataRow In pColumnTable.Rows
|
||||
Dim oExpr = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
|
||||
If oExpr = String.Empty Then Continue For
|
||||
|
||||
Dim referencedColumns = GetReferencedColumnNames(oExpr)
|
||||
If referencedColumns.Any(Function(col) String.Equals(col, e.Column.FieldName, StringComparison.OrdinalIgnoreCase)) Then
|
||||
oFormulaColumnsToRefresh.Add(oColumnData.Item("SPALTENNAME").ToString())
|
||||
End If
|
||||
Next
|
||||
|
||||
If oFormulaColumnsToRefresh.Count = 0 Then
|
||||
Return
|
||||
End If
|
||||
|
||||
' *** FALLBACK: Nur wenn EditValueChanged NICHT gefeuert hat ***
|
||||
' (z.B. bei programmatischer SetRowCellValue oder Paste)
|
||||
Dim oRowHandle As Integer = e.RowHandle
|
||||
_Logger.Debug("[FormulaRefresh] CellValueChanged FALLBACK – refreshing for row [{0}] after column [{1}] changed.", oRowHandle, e.Column.FieldName)
|
||||
|
||||
oView.GridControl.BeginInvoke(New Action(
|
||||
Sub()
|
||||
Try
|
||||
If Not oView.IsValidRowHandle(oRowHandle) Then Return
|
||||
|
||||
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
|
||||
Dim oGridColumn As GridColumn = oView.Columns.ColumnByFieldName(oFormulaColumnName)
|
||||
If oGridColumn Is Nothing Then Continue For
|
||||
|
||||
oView.RefreshRowCell(oRowHandle, oGridColumn)
|
||||
_Logger.Debug("[FormulaRefresh] FALLBACK DisplayText for [{0}]: [{1}]",
|
||||
oFormulaColumnName, oView.GetRowCellDisplayText(oRowHandle, oGridColumn))
|
||||
Next
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
End Sub))
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
End Sub
|
||||
Private Sub HandleInheritedColumnValue(pView As GridView, pColumnDefinition As DataTable, pArgs As CellValueChangedEventArgs)
|
||||
If pView Is Nothing OrElse pArgs Is Nothing OrElse pArgs.Column Is Nothing Then
|
||||
Return
|
||||
End If
|
||||
' *** NEU: Bei Formel-Refresh überspringen ***
|
||||
If _isRefreshingFormula Then
|
||||
_Logger.Debug("Skipping HandleInheritedColumnValue during formula refresh.")
|
||||
Return
|
||||
End If
|
||||
|
||||
If isApplyingInheritedValue OrElse pArgs.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||
Return
|
||||
@@ -642,28 +863,12 @@ Namespace ControlCreator
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub View_ShowingEditor(sender As Object, e As CancelEventArgs)
|
||||
Dim view As GridView = TryCast(sender, GridView)
|
||||
_Logger.Debug("Showing editor.")
|
||||
If view.IsNewItemRow(view.FocusedRowHandle) AndAlso Not newRowModified Then
|
||||
_Logger.Debug("Adding new row.")
|
||||
view.AddNewRow()
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub View_ShownEditor(sender As Object, e As EventArgs)
|
||||
Dim view As GridView = TryCast(sender, GridView)
|
||||
If view.IsNewItemRow(view.FocusedRowHandle) Then
|
||||
_Logger.Debug("Attaching Modified Handler.")
|
||||
AddHandler view.ActiveEditor.Modified, Sub()
|
||||
_Logger.Debug("Row was modified.")
|
||||
newRowModified = True
|
||||
End Sub
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub View_ValidateRow(sender As Object, e As ValidateRowEventArgs)
|
||||
Dim view As GridView = TryCast(sender, GridView)
|
||||
' RowHandle für RowUpdated merken, bevor er sich nach dem Commit ändert
|
||||
|
||||
If view.IsNewItemRow(e.RowHandle) AndAlso Not newRowModified Then
|
||||
_Logger.Debug("Deleting unused row")
|
||||
view.DeleteRow(e.RowHandle)
|
||||
|
||||
@@ -98,8 +98,13 @@ Public Class clsPatterns
|
||||
lookup.Properties.SelectedValues = New List(Of String) From {newValue.ToString()}
|
||||
End If
|
||||
|
||||
Case GetType(Windows.Forms.ComboBox)
|
||||
DirectCast(ctrl, ComboBox).Text = newValue?.ToString()
|
||||
' ========== FIX START: Beide ComboBox-Typen unterstützen ==========
|
||||
Case GetType(System.Windows.Forms.ComboBox)
|
||||
DirectCast(ctrl, System.Windows.Forms.ComboBox).Text = newValue?.ToString()
|
||||
|
||||
Case GetType(DevExpress.XtraEditors.ComboBoxEdit)
|
||||
DirectCast(ctrl, DevExpress.XtraEditors.ComboBoxEdit).Text = newValue?.ToString()
|
||||
' ========== FIX END ==========
|
||||
|
||||
Case GetType(CheckBox)
|
||||
If TypeOf newValue Is Boolean Then
|
||||
|
||||
@@ -2,8 +2,21 @@
|
||||
|
||||
Public Class frmError
|
||||
Public ValidatorError As String = ""
|
||||
Private _isClosing As Boolean = False
|
||||
|
||||
Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
|
||||
Me.Close()
|
||||
' ========== FIX 1: Event-Handler SOFORT deregistrieren ==========
|
||||
RemoveHandler OK_Button.Click, AddressOf OK_Button_Click
|
||||
|
||||
' ========== DIAGNOSE: StackTrace ausgeben ==========
|
||||
Dim st As New StackTrace(True)
|
||||
LOGGER.Debug($"[frmError] OK_Button_Click aufgerufen von:")
|
||||
For Each frame As StackFrame In st.GetFrames()
|
||||
LOGGER.Debug($" {frame.GetMethod()?.DeclaringType?.Name}.{frame.GetMethod()?.Name} (Zeile {frame.GetFileLineNumber()})")
|
||||
Next
|
||||
' ========== ENDE DIAGNOSE ==========
|
||||
|
||||
CloseDialog()
|
||||
End Sub
|
||||
|
||||
Private Sub frmError_Load(sender As Object, e As System.EventArgs) Handles Me.Load
|
||||
@@ -27,7 +40,45 @@ Public Class frmError
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Sub frmError_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
|
||||
Me.Label1.Focus()
|
||||
Private Sub CloseDialog()
|
||||
' ========== FIX 2: Guard mit Dispose-Check ==========
|
||||
If _isClosing OrElse Me.IsDisposed Then
|
||||
LOGGER.Debug($"[frmError] CloseDialog blockiert (isClosing={_isClosing}, IsDisposed={Me.IsDisposed})")
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
_isClosing = True
|
||||
LOGGER.Debug($"[frmError] CloseDialog: Flag gesetzt, starte verzögerten Close")
|
||||
|
||||
' ========== FIX 3: VERZÖGERTER Close via BeginInvoke ==========
|
||||
' KRITISCH: Close wird NACH Abschluss des aktuellen Event-Handlers ausgeführt
|
||||
Me.BeginInvoke(New Action(Sub()
|
||||
If Not Me.IsDisposed Then
|
||||
Me.DialogResult = DialogResult.OK
|
||||
Me.Close()
|
||||
LOGGER.Debug($"[frmError] Dialog geschlossen via BeginInvoke")
|
||||
End If
|
||||
End Sub))
|
||||
' ========== ENDE FIX 3 ==========
|
||||
End Sub
|
||||
Private Sub frmError_Shown(sender As Object, e As EventArgs) Handles Me.Shown
|
||||
Me.Label1.Focus()
|
||||
LOGGER.Debug($"[frmError] Dialog angezeigt - Enabled: {Me.Enabled}")
|
||||
End Sub
|
||||
|
||||
Private Sub frmError_Activated(sender As Object, e As EventArgs) Handles Me.Activated
|
||||
LOGGER.Debug($"[frmError] Dialog aktiviert")
|
||||
End Sub
|
||||
' ========== FIX 4: FormClosing-Handler hinzufügen ==========
|
||||
Private Sub frmError_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
|
||||
If _isClosing Then
|
||||
LOGGER.Debug($"[frmError] FormClosing: Close bereits aktiv, erlauben")
|
||||
Return
|
||||
End If
|
||||
|
||||
' Falls Close von außen (z.B. [X]-Button) ausgelöst wurde
|
||||
_isClosing = True
|
||||
LOGGER.Debug($"[frmError] FormClosing: Flag gesetzt via FormClosing")
|
||||
End Sub
|
||||
' ========== ENDE FIX 4 ==========
|
||||
End Class
|
||||
|
||||
@@ -136,6 +136,10 @@ Public Class frmValidator
|
||||
Private _isUpdatingLookup As Boolean = False
|
||||
Private _suppressLookupEvents As Boolean = False
|
||||
Private _overlayActive As Boolean = False
|
||||
Private _isShowingErrorDialog As Boolean = False ' ← NEU: Klassenvariable oben hinzufügen
|
||||
Private _overlayHandle As Object = Nothing ' ← NEU: Klassenvariable
|
||||
|
||||
|
||||
Private Class Translation_Strings
|
||||
Inherits My.Resources.frmValidator_Strings
|
||||
End Class
|
||||
@@ -2084,9 +2088,17 @@ Public Class frmValidator
|
||||
If oView.FocusedRowHandle < 0 Then Exit Sub
|
||||
' Nicht löschen wenn eine Zelle gerade bearbeitet wird
|
||||
If oView.ActiveEditor IsNot Nothing Then Exit Sub
|
||||
|
||||
Dim oGrid As GridControl = oView.GridControl
|
||||
Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata)
|
||||
|
||||
If oMeta IsNot Nothing AndAlso oMeta.ReadOnly Then
|
||||
MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] ist ReadOnly → Löschen blockiert")
|
||||
e.Handled = True
|
||||
e.SuppressKeyPress = True
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
|
||||
If oMeta IsNot Nothing Then
|
||||
oMeta.IsDirty = True
|
||||
MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] marked as dirty")
|
||||
@@ -5188,20 +5200,34 @@ Public Class frmValidator
|
||||
End If
|
||||
btnSave.Enabled = False
|
||||
' ========== ENDE FIX 1 ==========
|
||||
Dim oHandle = SplashScreenManager.ShowOverlayForm(Me)
|
||||
|
||||
' ========== FIX 2: Overlay-Handle global speichern ==========
|
||||
_overlayHandle = SplashScreenManager.ShowOverlayForm(Me)
|
||||
_overlayActive = True
|
||||
' ========== ENDE FIX 2 ==========
|
||||
|
||||
Try
|
||||
If ForceGridValidation() = True Then
|
||||
Finish_WFStep()
|
||||
End If
|
||||
Finally
|
||||
' ========== FIX 2: Nur Enable wenn Form NICHT schließt ==========
|
||||
' ========== FIX 3: Overlay IMMER schließen ==========
|
||||
_overlayActive = False
|
||||
Try
|
||||
SplashScreenManager.CloseOverlayForm(_overlayHandle)
|
||||
Catch ex As Exception
|
||||
MyValidationLogger.Warn($"⚠️ [btnSave_Click] Overlay-Close failed: {ex.Message}")
|
||||
End Try
|
||||
_overlayHandle = Nothing
|
||||
' ========== ENDE FIX 3 ==========
|
||||
|
||||
' ========== FIX 4: Button nur re-enablen wenn Form nicht schließt ==========
|
||||
If Not _FormClosing AndAlso Not Me.IsDisposed Then
|
||||
btnSave.Enabled = True
|
||||
Else
|
||||
MyValidationLogger.Debug("btnSave_Click: Form closing, Button bleibt disabled")
|
||||
End If
|
||||
SplashScreenManager.CloseOverlayForm(oHandle)
|
||||
' ========== ENDE FIX 2 ==========
|
||||
' ========== ENDE FIX 4 ==========
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
@@ -5710,12 +5736,20 @@ Public Class frmValidator
|
||||
End Try
|
||||
Else
|
||||
errormessage = oErrMsgMissingInput
|
||||
frmError.ShowDialog()
|
||||
MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Validierung fehlgeschlagen → OpenfrmError")
|
||||
OpenfrmError(oErrMsgMissingInput) ' ← Statt: frmError.ShowDialog()
|
||||
oErrorOcurred = True
|
||||
' ========== FIX: Overlay schließen NACH Dialog ==========
|
||||
If overlayStartedHere Then
|
||||
_overlayActive = False
|
||||
SplashScreenManager.CloseOverlayForm(oHandle)
|
||||
Try
|
||||
SplashScreenManager.CloseOverlayForm(_overlayHandle)
|
||||
Catch ex As Exception
|
||||
MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Overlay-Close failed: {ex.Message}")
|
||||
End Try
|
||||
_overlayHandle = Nothing
|
||||
End If
|
||||
' ========== ENDE FIX ==========
|
||||
Exit Sub
|
||||
End If
|
||||
Else
|
||||
@@ -5777,7 +5811,17 @@ Public Class frmValidator
|
||||
End If
|
||||
Focus_FirstControl()
|
||||
End If
|
||||
|
||||
' ========== FIX: Overlay schließen am Ende ==========
|
||||
If overlayStartedHere Then
|
||||
_overlayActive = False
|
||||
Try
|
||||
SplashScreenManager.CloseOverlayForm(_overlayHandle)
|
||||
Catch ex As Exception
|
||||
MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Overlay-Close failed: {ex.Message}")
|
||||
End Try
|
||||
_overlayHandle = Nothing
|
||||
End If
|
||||
' ========== ENDE FIX ==========
|
||||
If LOG_HOTSPOTS Then
|
||||
MyValidationLogger.Info($"[PERF] Finish_WFStep GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms")
|
||||
End If
|
||||
@@ -6181,6 +6225,11 @@ Public Class frmValidator
|
||||
oErrMsgMissingInput &= ":" & vbCrLf & oRegexMessage
|
||||
End If
|
||||
oControl.BackColor = Color.Red
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6246,6 +6295,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} as VEKTOR - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6259,6 +6313,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6282,6 +6341,11 @@ Public Class frmValidator
|
||||
Dim st As New StackTrace(True)
|
||||
st = New StackTrace(ex, True)
|
||||
MyValidationLogger.Warn("⚠️ Unexpected error in Check_UpdateIndexe TextBox :" & ex.Message, True)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
|
||||
' Nach Fehler: Dirty-Flag zurücksetzen
|
||||
@@ -6298,6 +6362,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Please Choose an entry out of ComboBox '" & cmb.Name & "'"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
Else
|
||||
@@ -6349,6 +6418,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing Combobox as VEKTOR - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6362,6 +6436,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing Combobox - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6371,6 +6450,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error indexing combobox idb"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6405,6 +6489,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Please Choose DateValue for field'" & dtp.Name & "'"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
ElseIf dtp.Value.ToString <> "01.01.0001 00:00:00" Then
|
||||
@@ -6425,6 +6514,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing DatePicker as VEKTOR - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6437,6 +6531,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing DatePicker- ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6445,6 +6544,16 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error indexing datepicker idb"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6477,6 +6586,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Please set Checkbox value for field '" & chk.Name & "'"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6525,6 +6639,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing Checkbox as VEKTOR - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6534,12 +6653,22 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing Checkbox - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
Else
|
||||
If IDBData.SetVariableValue(oIndexName, chk.Checked.ToString) Then
|
||||
oErrMsgMissingInput = "error indexing checkbox idb"
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6572,6 +6701,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Fehlende Eingabe in Vektorfeld '" & dgv.Name & "'"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
ElseIf Zeilen > 0 Then
|
||||
@@ -6608,6 +6742,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error while indexing Vektorfeld - ERROR: " & idxerr_message
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6618,6 +6757,11 @@ Public Class frmValidator
|
||||
oMissing = True
|
||||
oErrMsgMissingInput = "Error indexing Datagridview idb"
|
||||
MyValidationLogger.Warn(oErrMsgMissingInput)
|
||||
' Vor ShowDialog prüfen
|
||||
If _FormClosing Then
|
||||
MyValidationLogger.Warn("Form closing - skip error dialog")
|
||||
Return False
|
||||
End If
|
||||
OpenfrmError(oErrMsgMissingInput)
|
||||
Exit For
|
||||
End If
|
||||
@@ -6649,7 +6793,8 @@ Public Class frmValidator
|
||||
|
||||
Dim oResult = ValidateGridControl(oGrid, oSettings, oGridColumnDefinition, oMissing, oErrMsgMissingInput)
|
||||
If oResult = False Then
|
||||
Exit For
|
||||
MyValidationLogger.Warn($"⚠️ Validierung fehlgeschlagen für Grid [{oGrid.Name}] → Exit For")
|
||||
Exit For ' ← SOFORT stoppen, keinen zweiten Dialog!
|
||||
End If
|
||||
End Select
|
||||
|
||||
@@ -6691,9 +6836,30 @@ Public Class frmValidator
|
||||
|
||||
End Function
|
||||
Sub OpenfrmError(pErrormessage As String)
|
||||
Dim ofrm As New frmError
|
||||
ofrm.ValidatorError = pErrormessage
|
||||
ofrm.ShowDialog()
|
||||
' ========== FIX: Verhindere mehrfache Dialoge ==========
|
||||
If _isShowingErrorDialog Then
|
||||
MyValidationLogger.Warn("⚠️ [OpenfrmError] Dialog bereits offen → Exit Sub")
|
||||
Return
|
||||
End If
|
||||
_isShowingErrorDialog = True
|
||||
' ========== ENDE FIX ==========
|
||||
|
||||
' ========== KRITISCH: Overlay NICHT hier schließen! ==========
|
||||
' Das macht der Aufrufer (Finish_WFStep oder btnSave_Click)!
|
||||
' ========== ENDE KRITISCH ==========
|
||||
|
||||
' 2. Events blockieren
|
||||
_suppressLookupEvents = True
|
||||
Try
|
||||
Using ofrm As New frmError With {.ValidatorError = pErrormessage}
|
||||
ofrm.ShowDialog(Me)
|
||||
End Using
|
||||
Finally
|
||||
_suppressLookupEvents = False
|
||||
' ========== FIX: Guard zurücksetzen ==========
|
||||
_isShowingErrorDialog = False
|
||||
' ========== ENDE FIX ==========
|
||||
End Try
|
||||
End Sub
|
||||
Private Class ControlSettings
|
||||
Public Name As String
|
||||
@@ -6712,7 +6878,19 @@ Public Class frmValidator
|
||||
'Wenn kein Wert ausgewählt wurde und der Index aber gesetzt werden muss
|
||||
If pSettings.IsRequired = True And oRowCount = 0 Then
|
||||
pMissing = True
|
||||
pMissingMessage = "Fehlende Eingabe in Tabelle '" & pGrid.Name & "'"
|
||||
' ========== NEU: Liste der Required-Spalten sammeln ==========
|
||||
Dim requiredColumns = pColumnDefinition.AsEnumerable().
|
||||
Where(Function(row) row.ItemEx("VALIDATION", False) = True).
|
||||
Select(Function(row) row.ItemEx("SPALTEN_HEADER_LANG", row.ItemEx("SPALTENNAME", "")).ToString()).
|
||||
Where(Function(colName) Not String.IsNullOrWhiteSpace(colName)).
|
||||
ToList()
|
||||
|
||||
If requiredColumns.Count > 0 Then
|
||||
pMissingMessage = $"Missing input in table '{pGrid.Name}'. At least on row with following required fields necessary: {String.Join(", ", requiredColumns)}"
|
||||
Else
|
||||
pMissingMessage = $"Missing input in table '{pGrid.Name}' - at least one row necessary"
|
||||
End If
|
||||
' ========== ENDE NEU ==========
|
||||
pGrid.BackColor = Color.Red
|
||||
MyValidationLogger.Warn(pMissingMessage)
|
||||
|
||||
@@ -7364,6 +7542,8 @@ Public Class frmValidator
|
||||
DatabaseFallback.ExecuteNonQueryECM(ins)
|
||||
Else
|
||||
SetStatusLabel("Error while saving data!", "Red")
|
||||
MsgBox("Unexpeceted error while savign data! Please check Your log and try again.", MsgBoxStyle.Critical)
|
||||
|
||||
End If
|
||||
' ========== ENDE FIX 2 ==========
|
||||
Finally
|
||||
|
||||
Reference in New Issue
Block a user