Vor SetControlValuesChange
This commit is contained in:
@@ -68,7 +68,17 @@ Public Class ClassControlCreator
|
|||||||
''' </summary>
|
''' </summary>
|
||||||
Public Property GridTables As New Dictionary(Of Integer, Dictionary(Of String, RepositoryItem))
|
Public Property GridTables As New Dictionary(Of Integer, Dictionary(Of String, RepositoryItem))
|
||||||
Public Property GridColumns As New Dictionary(Of Integer, DataTable)
|
Public Property GridColumns As New Dictionary(Of Integer, DataTable)
|
||||||
|
Private _globalLookupEventGuard As Boolean = False
|
||||||
|
|
||||||
|
Public Property GlobalLookupEventGuard As Boolean
|
||||||
|
Get
|
||||||
|
Return _globalLookupEventGuard
|
||||||
|
End Get
|
||||||
|
Set(value As Boolean)
|
||||||
|
_globalLookupEventGuard = value
|
||||||
|
Logger.Debug($"GlobalLookupEventGuard -> gesetzt auf [{value}]")
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
|
||||||
|
|
||||||
''' <summary>
|
''' <summary>
|
||||||
@@ -853,7 +863,35 @@ Public Class ClassControlCreator
|
|||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Sub GridTables_HandleControlValueChange(pControlPanel As XtraScrollableControl, pColumnsWithSqlAndControlPlaceholders As DataTable)
|
Public Sub GridTables_HandleControlValueChange(pControlPanel As XtraScrollableControl, pColumnsWithSqlAndControlPlaceholders As DataTable)
|
||||||
If Not IsNothing(pColumnsWithSqlAndControlPlaceholders) AndAlso pColumnsWithSqlAndControlPlaceholders.Rows.Count > 0 Then
|
If pColumnsWithSqlAndControlPlaceholders Is Nothing OrElse pColumnsWithSqlAndControlPlaceholders.Rows.Count = 0 Then
|
||||||
|
Logger.Debug("No depending controls with SQL statements defined, skipping handling control value change.")
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
|
||||||
|
' ============================================================================
|
||||||
|
' Schritt 1 - Sichere ALLE Lookup-Werte VOR SQL-Reload
|
||||||
|
' ============================================================================
|
||||||
|
Dim lookupBackups As New Dictionary(Of String, Object)
|
||||||
|
|
||||||
|
For Each oControl As Control In pControlPanel.Controls
|
||||||
|
If TypeOf oControl Is LookupControl3 Then
|
||||||
|
Try
|
||||||
|
Dim lookup = DirectCast(oControl, LookupControl3)
|
||||||
|
' Speichere den aktuellen EditValue (kann einzelner Wert oder Liste sein)
|
||||||
|
If lookup.EditValue IsNot Nothing Then
|
||||||
|
Dim controlName As String = lookup.Name
|
||||||
|
lookupBackups(controlName) = lookup.EditValue
|
||||||
|
Logger.Debug($"GridTables_HandleControlValueChange -> Backup für Lookup [{controlName}]: [{lookup.EditValue}]")
|
||||||
|
End If
|
||||||
|
Catch ex As Exception
|
||||||
|
Logger.Error($"GridTables_HandleControlValueChange -> Fehler beim Backup von Lookup: {ex.Message}")
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
' ============================================================================
|
||||||
|
' Schritt 2 - Verarbeite Grid-Columns mit SQL-Abhängigkeiten
|
||||||
|
' ============================================================================
|
||||||
For Each oRow As DataRow In pColumnsWithSqlAndControlPlaceholders.Rows
|
For Each oRow As DataRow In pColumnsWithSqlAndControlPlaceholders.Rows
|
||||||
Try
|
Try
|
||||||
Dim oSqlStatement = oRow.ItemEx("SQL_COMMAND", String.Empty)
|
Dim oSqlStatement = oRow.ItemEx("SQL_COMMAND", String.Empty)
|
||||||
@@ -862,35 +900,202 @@ Public Class ClassControlCreator
|
|||||||
Dim oColumnName = oRow.Item("SPALTENNAME")
|
Dim oColumnName = oRow.Item("SPALTENNAME")
|
||||||
Dim oAdvancedLookup = oRow.Item("ADVANCED_LOOKUP")
|
Dim oAdvancedLookup = oRow.Item("ADVANCED_LOOKUP")
|
||||||
|
|
||||||
If oSqlStatement <> String.Empty And oConnectionId > -1 Then
|
If oSqlStatement <> String.Empty AndAlso oConnectionId > -1 Then
|
||||||
oSqlStatement = clsPatterns.ReplaceAllValues(oSqlStatement, pControlPanel, True)
|
oSqlStatement = clsPatterns.ReplaceAllValues(oSqlStatement, pControlPanel, True)
|
||||||
|
|
||||||
GridTables_CacheDatatableForColumn(oControlId, oColumnName, oSqlStatement, oConnectionId, oAdvancedLookup)
|
GridTables_CacheDatatableForColumn(oControlId, oColumnName, oSqlStatement, oConnectionId, oAdvancedLookup)
|
||||||
|
|
||||||
|
' Force-setting Editor for GridColumns
|
||||||
' === Block to force setting the editor for GridColumns
|
|
||||||
Logger.Debug("Force-setting Editor for all Gridcells..")
|
Logger.Debug("Force-setting Editor for all Gridcells..")
|
||||||
For Each oControl As Control In pControlPanel.Controls
|
For Each oControl As Control In pControlPanel.Controls
|
||||||
Try
|
Try
|
||||||
Dim oMeta = DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata)
|
If oControl.Tag IsNot Nothing AndAlso TypeOf oControl.Tag Is ControlMetadata Then
|
||||||
|
Dim oMeta = DirectCast(oControl.Tag, ControlMetadata)
|
||||||
If oMeta.Guid = oControlId AndAlso TypeOf oControl Is GridControl Then
|
If oMeta.Guid = oControlId AndAlso TypeOf oControl Is GridControl Then
|
||||||
Dim oGrid As GridControl = DirectCast(oControl, GridControl)
|
Dim oGrid As GridControl = DirectCast(oControl, GridControl)
|
||||||
|
If oGrid.FocusedView IsNot Nothing AndAlso TypeOf oGrid.FocusedView Is GridView Then
|
||||||
DirectCast(oGrid.FocusedView, GridView).FocusInvalidRow()
|
DirectCast(oGrid.FocusedView, GridView).FocusInvalidRow()
|
||||||
Logger.Debug("Force-setting Editor for Grid [{0}]", oGrid.Name)
|
Logger.Debug($"Force-setting Editor for Grid [{oGrid.Name}]")
|
||||||
|
End If
|
||||||
Exit For
|
Exit For
|
||||||
End If
|
End If
|
||||||
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Error(ex)
|
Logger.Error($"GridTables_HandleControlValueChange -> Fehler beim Force-setting Editor: {ex.Message}")
|
||||||
End Try
|
End Try
|
||||||
Next
|
Next
|
||||||
' === End
|
|
||||||
|
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Logger.Error(ex)
|
Logger.Error(ex)
|
||||||
Logger.Info("Unexpected Error in Display SQL result for grid column: " & oRow.Item("CONTROL_ID") & " - ERROR: " & ex.Message)
|
Logger.Info($"Unexpected Error in Display SQL result for grid column: {oRow.Item("CONTROL_ID")} - ERROR: {ex.Message}")
|
||||||
End Try
|
End Try
|
||||||
Next
|
Next
|
||||||
|
|
||||||
|
' ============================================================================
|
||||||
|
' Schritt 3 - Prüfe und restauriere Lookup-Werte mit SQL-Abhängigkeiten
|
||||||
|
' ============================================================================
|
||||||
|
If lookupBackups.Count > 0 Then
|
||||||
|
Logger.Debug($"GridTables_HandleControlValueChange -> Prüfe {lookupBackups.Count} Lookups auf Wiederherstellung...")
|
||||||
|
|
||||||
|
For Each oControl As Control In pControlPanel.Controls
|
||||||
|
If TypeOf oControl Is LookupControl3 Then
|
||||||
|
Try
|
||||||
|
Dim lookup = DirectCast(oControl, LookupControl3)
|
||||||
|
Dim controlName As String = lookup.Name
|
||||||
|
|
||||||
|
' Wenn wir einen Backup für dieses Lookup haben
|
||||||
|
If lookupBackups.ContainsKey(controlName) Then
|
||||||
|
Dim oldValue = lookupBackups(controlName)
|
||||||
|
|
||||||
|
' Prüfe ob Lookup ein DataSource hat (könnte durch SQL neu geladen worden sein)
|
||||||
|
If lookup.Properties.DataSource IsNot Nothing AndAlso TypeOf lookup.Properties.DataSource Is DataTable Then
|
||||||
|
Dim currentDataSource = DirectCast(lookup.Properties.DataSource, DataTable)
|
||||||
|
|
||||||
|
' Wenn DataSource Rows hat, versuche Werte wiederherzustellen
|
||||||
|
If currentDataSource.Rows.Count > 0 Then
|
||||||
|
RestoreLookupValues(lookup, oldValue, currentDataSource, controlName)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
Logger.Error($"GridTables_HandleControlValueChange -> Fehler beim Prüfen von Lookup: {ex.Message}")
|
||||||
|
Logger.Error(ex)
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
|
Next
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Sub RestoreLookupValues(lookup As LookupControl3, oldValue As Object,
|
||||||
|
newDataSource As DataTable, controlName As String)
|
||||||
|
If lookup Is Nothing OrElse oldValue Is Nothing OrElse newDataSource Is Nothing Then
|
||||||
|
Logger.Warn($"RestoreLookupValues -> [{controlName}] Ungültige Parameter")
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
|
||||||
|
Try
|
||||||
|
' Bestimme ValueColumn
|
||||||
|
Dim valueColumn As String = String.Empty
|
||||||
|
If String.IsNullOrEmpty(lookup.Properties.ValueMember) AndAlso newDataSource.Columns.Count > 0 Then
|
||||||
|
valueColumn = newDataSource.Columns(0).ColumnName
|
||||||
|
ElseIf Not String.IsNullOrEmpty(lookup.Properties.ValueMember) Then
|
||||||
|
valueColumn = lookup.Properties.ValueMember
|
||||||
|
Else
|
||||||
|
Logger.Warn($"RestoreLookupValues -> [{controlName}] Keine ValueColumn verfügbar")
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Build HashSet für effiziente Suche
|
||||||
|
Dim availableValues As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
|
||||||
|
For Each row As DataRow In newDataSource.Rows
|
||||||
|
If Not IsDBNull(row(valueColumn)) Then
|
||||||
|
availableValues.Add(row(valueColumn).ToString())
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
' Prüfe ob der alte Wert noch in der neuen DataSource existiert
|
||||||
|
Dim validValue As Object = Nothing
|
||||||
|
|
||||||
|
' Behandle verschiedene Datentypen (String, List, Array, etc.)
|
||||||
|
If TypeOf oldValue Is String Then
|
||||||
|
Dim valueStr As String = oldValue.ToString()
|
||||||
|
If availableValues.Contains(valueStr) Then
|
||||||
|
validValue = oldValue
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] Wert [{valueStr}] ✓ gefunden")
|
||||||
|
Else
|
||||||
|
Logger.Warn($"RestoreLookupValues -> [{controlName}] Wert [{valueStr}] ✗ nicht mehr vorhanden")
|
||||||
|
End If
|
||||||
|
ElseIf TypeOf oldValue Is IEnumerable Then
|
||||||
|
' Behandle Listen/Arrays
|
||||||
|
Dim validValues As New List(Of Object)
|
||||||
|
For Each item As Object In DirectCast(oldValue, IEnumerable)
|
||||||
|
If item IsNot Nothing Then
|
||||||
|
Dim itemStr As String = item.ToString()
|
||||||
|
If availableValues.Contains(itemStr) Then
|
||||||
|
validValues.Add(item)
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] Wert [{itemStr}] ✓ gefunden")
|
||||||
|
Else
|
||||||
|
Logger.Warn($"RestoreLookupValues -> [{controlName}] Wert [{itemStr}] ✗ nicht mehr vorhanden")
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
If validValues.Count > 0 Then
|
||||||
|
validValue = validValues
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
' Fallback für andere Typen
|
||||||
|
Dim valueStr As String = oldValue.ToString()
|
||||||
|
If availableValues.Contains(valueStr) Then
|
||||||
|
validValue = oldValue
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] Wert [{valueStr}] ✓ gefunden")
|
||||||
|
Else
|
||||||
|
Logger.Warn($"RestoreLookupValues -> [{controlName}] Wert [{valueStr}] ✗ nicht mehr vorhanden")
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Gültige Werte wiederherstellen
|
||||||
|
If validValue IsNot Nothing Then
|
||||||
|
' Event-Guard temporär aktivieren um Endlosschleifen zu vermeiden
|
||||||
|
Dim oldGuard As Boolean = GlobalLookupEventGuard
|
||||||
|
GlobalLookupEventGuard = True
|
||||||
|
|
||||||
|
Try
|
||||||
|
' Prüfe ob bereits korrekt gesetzt
|
||||||
|
Dim currentValue = lookup.EditValue
|
||||||
|
If currentValue IsNot Nothing AndAlso currentValue.Equals(validValue) Then
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] Wert bereits korrekt gesetzt")
|
||||||
|
Return
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Setze den Wert neu
|
||||||
|
lookup.EditValue = Nothing
|
||||||
|
Application.DoEvents()
|
||||||
|
|
||||||
|
lookup.EditValue = validValue
|
||||||
|
lookup.Refresh()
|
||||||
|
Application.DoEvents()
|
||||||
|
|
||||||
|
' Validierung
|
||||||
|
Dim newValue = lookup.EditValue
|
||||||
|
If newValue IsNot Nothing AndAlso newValue.Equals(validValue) Then
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] ✓ erfolgreich wiederhergestellt: [{validValue}]")
|
||||||
|
Else
|
||||||
|
Logger.Error($"RestoreLookupValues -> [{controlName}] ✗ Fehler beim Wiederherstellen! Erwartet: [{validValue}], Ist: [{If(newValue, "NULL")}]")
|
||||||
|
|
||||||
|
' Retry mit BeginUpdate/EndUpdate
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] Versuche alternative Methode mit BeginUpdate...")
|
||||||
|
lookup.Properties.BeginUpdate()
|
||||||
|
Try
|
||||||
|
lookup.EditValue = Nothing
|
||||||
|
Application.DoEvents()
|
||||||
|
lookup.EditValue = validValue
|
||||||
|
Finally
|
||||||
|
lookup.Properties.EndUpdate()
|
||||||
|
End Try
|
||||||
|
|
||||||
|
lookup.Refresh()
|
||||||
|
Application.DoEvents()
|
||||||
|
|
||||||
|
Dim retryValue = lookup.EditValue
|
||||||
|
If retryValue IsNot Nothing AndAlso retryValue.Equals(validValue) Then
|
||||||
|
Logger.Debug($"RestoreLookupValues -> [{controlName}] ✓ Alternative Methode erfolgreich")
|
||||||
|
Else
|
||||||
|
Logger.Error($"RestoreLookupValues -> [{controlName}] ✗ Auch alternative Methode fehlgeschlagen!")
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
Finally
|
||||||
|
' Event-Guard wiederherstellen
|
||||||
|
GlobalLookupEventGuard = oldGuard
|
||||||
|
End Try
|
||||||
|
Else
|
||||||
|
Logger.Info($"RestoreLookupValues -> [{controlName}] Keine gültigen Werte zum Wiederherstellen")
|
||||||
|
End If
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
Logger.Error($"RestoreLookupValues -> Fehler bei [{controlName}]: {ex.Message}")
|
||||||
|
Logger.Error(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@@ -28,13 +28,31 @@ Namespace ControlCreator
|
|||||||
Private _FormulaColumnNames As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
|
Private _FormulaColumnNames As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
|
||||||
Private _isRefreshingFormula As Boolean = False ' *** NEU: Flag für Formel-Refresh ***
|
Private _isRefreshingFormula As Boolean = False ' *** NEU: Flag für Formel-Refresh ***
|
||||||
Private _currencySymbol As String = "€"
|
Private _currencySymbol As String = "€"
|
||||||
|
''' <summary>
|
||||||
|
''' SHARED Dictionary: Speichert das aktuelle Währungssymbol PRO GridView (via Name).
|
||||||
|
''' Dies ist notwendig, weil UpdateCurrencyFormat auf einer NEUEN GridControl-Instanz
|
||||||
|
''' aufgerufen wird, der CustomColumnDisplayText-Handler aber auf der URSPRÜNGLICHEN
|
||||||
|
''' Instanz registriert wurde. Durch das Shared Dictionary können alle Instanzen
|
||||||
|
''' auf das aktuelle Symbol zugreifen.
|
||||||
|
''' </summary>
|
||||||
|
Private Shared _CurrencySymbolByGridName As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
|
||||||
Public Sub New(pLogConfig As LogConfig, pGridTables As Dictionary(Of Integer, Dictionary(Of String, RepositoryItem)), pCurrencySymbol As String)
|
Public Sub New(pLogConfig As LogConfig, pGridTables As Dictionary(Of Integer, Dictionary(Of String, RepositoryItem)), pCurrencySymbol As String)
|
||||||
_LogConfig = pLogConfig
|
_LogConfig = pLogConfig
|
||||||
_Logger = pLogConfig.GetLogger()
|
_Logger = pLogConfig.GetLogger()
|
||||||
_GridTables = pGridTables
|
_GridTables = pGridTables
|
||||||
_currencySymbol = pCurrencySymbol
|
_currencySymbol = pCurrencySymbol
|
||||||
End Sub
|
End Sub
|
||||||
|
''' <summary>
|
||||||
|
''' Setzt den Shared Currency-Cache zurück. Muss beim Laden eines neuen Dokuments
|
||||||
|
''' aufgerufen werden, bevor UpdateCurrencyFormat die neuen Werte schreibt.
|
||||||
|
''' Verhindert, dass ein veraltetes Währungssymbol aus einem vorherigen Dokument
|
||||||
|
''' durch den CustomColumnDisplayText-Handler verwendet wird.
|
||||||
|
''' </summary>
|
||||||
|
Public Shared Sub ResetCurrencySymbolCache()
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
_CurrencySymbolByGridName.Clear()
|
||||||
|
End SyncLock
|
||||||
|
End Sub
|
||||||
Public Function CreateGridColumns(pColumnTable As DataTable) As DataTable
|
Public Function CreateGridColumns(pColumnTable As DataTable) As DataTable
|
||||||
Dim oDataTable As New DataTable
|
Dim oDataTable As New DataTable
|
||||||
Dim columnsWithExpressions As New List(Of Tuple(Of DataColumn, String))
|
Dim columnsWithExpressions As New List(Of Tuple(Of DataColumn, String))
|
||||||
@@ -202,15 +220,129 @@ Namespace ControlCreator
|
|||||||
Return oEditor
|
Return oEditor
|
||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
|
''' <summary>
|
||||||
|
''' Setzt das Währungssymbol für ein bestimmtes Grid im Shared Cache.
|
||||||
|
''' Muss bei JEDEM Dokumentwechsel aufgerufen werden (auch bei EUR),
|
||||||
|
''' damit der CustomColumnDisplayText-Handler sofort den korrekten Wert hat.
|
||||||
|
''' </summary>
|
||||||
|
Public Shared Sub SetCurrencySymbolForGrid(gridName As String, currencySymbol As String)
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
_CurrencySymbolByGridName(gridName) = currencySymbol
|
||||||
|
End SyncLock
|
||||||
|
End Sub
|
||||||
' Hilfsroutine: passt NUR das Summary-Item an (ohne FormatInfo)
|
' Hilfsroutine: passt NUR das Summary-Item an (ohne FormatInfo)
|
||||||
Private Sub ApplyCurrencySummaryFormat(oCol As GridColumn)
|
Private Sub ApplyCurrencySummaryFormat(oCol As GridColumn)
|
||||||
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
||||||
' Variante A: Standard-Währungsformat aus aktueller Kultur
|
_Logger.Debug("Applying currency summary format for column [{0}] with symbol [{1}]", oCol.FieldName, _currencySymbol)
|
||||||
' oCol.SummaryItem.DisplayFormat = "SUM: {0:C2}"
|
|
||||||
|
|
||||||
' Variante B: Kulturunabhängig, Symbol explizit anhängen
|
' Variante B: Kulturunabhängig, Symbol explizit anhängen
|
||||||
oCol.SummaryItem.DisplayFormat = $"SUM: {{0:N2}} {_currencySymbol}"
|
oCol.SummaryItem.DisplayFormat = $"{{0:N2}} {_currencySymbol}"
|
||||||
End Sub
|
End Sub
|
||||||
|
''' <summary>
|
||||||
|
''' Aktualisiert die Währungsformatierung für alle CURRENCY-Spalten mit neuem Währungssymbol.
|
||||||
|
''' Betrifft DisplayFormat, ColumnEdit (für editierbare Spalten) und Summary-Footer.
|
||||||
|
''' </summary>
|
||||||
|
''' <summary>
|
||||||
|
'''
|
||||||
|
Public Sub UpdateCurrencyFormat(pColumnTable As DataTable, pGridView As GridView, pGrid As DevExpress.XtraGrid.GridControl, pNewCurrencySymbol As String)
|
||||||
|
Try
|
||||||
|
_Logger.Info("[UpdateCurrencyFormat] *** START *** [{0}] → [{1}] für [{2}]", _currencySymbol, pNewCurrencySymbol, pGrid.Name)
|
||||||
|
|
||||||
|
' *** KERN-FIX: Speichere Symbol im SHARED Dictionary ***
|
||||||
|
Dim gridName As String = pGrid.Name
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
If _CurrencySymbolByGridName.ContainsKey(gridName) Then
|
||||||
|
_CurrencySymbolByGridName(gridName) = pNewCurrencySymbol
|
||||||
|
Else
|
||||||
|
_CurrencySymbolByGridName.Add(gridName, pNewCurrencySymbol)
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
_Logger.Debug("[UpdateCurrencyFormat] Shared Dictionary updated: [{0}] = [{1}]", gridName, pNewCurrencySymbol)
|
||||||
|
|
||||||
|
_currencySymbol = pNewCurrencySymbol
|
||||||
|
|
||||||
|
Dim oCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
||||||
|
oCultureInfo.NumberFormat.CurrencySymbol = _currencySymbol
|
||||||
|
|
||||||
|
Dim riTextEdit As New RepositoryItemTextEdit()
|
||||||
|
riTextEdit.MaskSettings.Configure(Of MaskSettings.Numeric)(
|
||||||
|
Sub(settings)
|
||||||
|
settings.MaskExpression = "c"
|
||||||
|
settings.Culture = oCultureInfo
|
||||||
|
End Sub)
|
||||||
|
riTextEdit.UseMaskAsDisplayFormat = False
|
||||||
|
riTextEdit.DisplayFormat.FormatType = FormatType.Custom
|
||||||
|
riTextEdit.DisplayFormat.FormatString = $"#,##0.00 {_currencySymbol}"
|
||||||
|
_Logger.Debug("[UpdateCurrencyFormat] riTextEdit: DisplayFormat=[{0}]",
|
||||||
|
riTextEdit.DisplayFormat.FormatString)
|
||||||
|
|
||||||
|
pGridView.BeginUpdate()
|
||||||
|
Try
|
||||||
|
' Schritt 1: Altes RepositoryItem entfernen (ohne vorher ColumnEdit=Nothing)
|
||||||
|
' ColumnEdit NICHT auf Nothing setzen – das würde einen Zwischenrender auslösen
|
||||||
|
Dim oldItems = pGrid.RepositoryItems.OfType(Of RepositoryItemTextEdit)().
|
||||||
|
Where(Function(item) item.MaskSettings.MaskExpression = "c").ToList()
|
||||||
|
For Each oldItem In oldItems
|
||||||
|
_Logger.Debug("[UpdateCurrencyFormat] Removing old riTextEdit: DisplayFormat=[{0}]",
|
||||||
|
oldItem.DisplayFormat.FormatString)
|
||||||
|
pGrid.RepositoryItems.Remove(oldItem)
|
||||||
|
Next
|
||||||
|
|
||||||
|
' Schritt 2: CURRENCY-Spalten konfigurieren
|
||||||
|
For Each oCol As GridColumn In pGridView.Columns
|
||||||
|
Dim oColumnData As DataRow = pColumnTable.
|
||||||
|
Select($"SPALTENNAME = '{oCol.FieldName}'").
|
||||||
|
FirstOrDefault()
|
||||||
|
If oColumnData Is Nothing Then Continue For
|
||||||
|
|
||||||
|
If ObjectEx.NotNull(oColumnData.Item("TYPE_COLUMN"), String.Empty).ToString() <> "CURRENCY" Then Continue For
|
||||||
|
|
||||||
|
Dim oIsFormula As Boolean =
|
||||||
|
ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty) <> String.Empty
|
||||||
|
|
||||||
|
' DisplayFormat immer aktualisieren
|
||||||
|
oCol.DisplayFormat.FormatType = FormatType.Custom
|
||||||
|
oCol.DisplayFormat.FormatString = $"#,##0.00 {_currencySymbol}"
|
||||||
|
|
||||||
|
If Not oIsFormula AndAlso oCol.OptionsColumn.AllowEdit Then
|
||||||
|
' Direkt neues RepositoryItem setzen – kein Umweg über RepositoryItems-Collection
|
||||||
|
oCol.ColumnEdit = riTextEdit
|
||||||
|
_Logger.Debug("[UpdateCurrencyFormat] ColumnEdit=[{0}] für [{1}]",
|
||||||
|
DirectCast(oCol.ColumnEdit, RepositoryItemTextEdit).DisplayFormat.FormatString,
|
||||||
|
oCol.FieldName)
|
||||||
|
End If
|
||||||
|
|
||||||
|
If ObjectEx.NotNull(oColumnData.Item("SUMMARY_FUNCTION"), String.Empty) =
|
||||||
|
Constants.AGGREGATE_TOTAL_CURRENCY Then
|
||||||
|
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
||||||
|
oCol.SummaryItem.DisplayFormat = $"{{0:N2}} {_currencySymbol}"
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
Finally
|
||||||
|
pGridView.EndUpdate()
|
||||||
|
End Try
|
||||||
|
|
||||||
|
' *** KEIN DataSource-Rebind ***
|
||||||
|
' DataSource-Rebind (pGrid.DataSource = Nothing / = oCurrentDataSource) wirft
|
||||||
|
' den gecachten Display-Text weg und erzwingt einen Neu-Render durch DevExpress.
|
||||||
|
' Dabei greift DevExpress auf die Mask-Formatierung des RepositoryItems zurück
|
||||||
|
' (z.B. "c" mit EUR-Culture) statt auf DisplayFormat → EUR bleibt sichtbar.
|
||||||
|
' Stattdessen: LayoutChanged + alle Zeilen invalidieren → DevExpress rendert
|
||||||
|
' die Zellen neu mit dem aktualisierten DisplayFormat und ColumnEdit.
|
||||||
|
pGridView.LayoutChanged()
|
||||||
|
For i As Integer = 0 To pGridView.DataRowCount - 1
|
||||||
|
pGridView.InvalidateRow(i)
|
||||||
|
Next
|
||||||
|
pGridView.UpdateTotalSummary()
|
||||||
|
|
||||||
|
_Logger.Info("[UpdateCurrencyFormat] *** END *** _currencySymbol=[{0}]", _currencySymbol)
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
_Logger.Error("[UpdateCurrencyFormat] Fehler: {0}", ex.Message)
|
||||||
|
_Logger.Error(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
|
||||||
Public Sub ConfigureViewColumns(pColumnTable As DataTable, pGridView As GridView, pGrid As DevExpress.XtraGrid.GridControl)
|
Public Sub ConfigureViewColumns(pColumnTable As DataTable, pGridView As GridView, pGrid As DevExpress.XtraGrid.GridControl)
|
||||||
Dim oShouldDisplayFooter As Boolean = False
|
Dim oShouldDisplayFooter As Boolean = False
|
||||||
For Each oCol As GridColumn In pGridView.Columns
|
For Each oCol As GridColumn In pGridView.Columns
|
||||||
@@ -256,8 +388,13 @@ Namespace ControlCreator
|
|||||||
oCol.DisplayFormat.FormatString = "N2"
|
oCol.DisplayFormat.FormatString = "N2"
|
||||||
|
|
||||||
Case "CURRENCY"
|
Case "CURRENCY"
|
||||||
oCol.DisplayFormat.FormatType = FormatType.Custom
|
' *** DisplayFormat wird NICHT hier gesetzt ***
|
||||||
oCol.DisplayFormat.FormatString = $"N2 {_currencySymbol}"
|
' ConfigureViewColumnsCurrency übernimmt die CURRENCY-Formatierung
|
||||||
|
' mit dem korrekten _currencySymbol. Dieses Standardformat würde
|
||||||
|
' später von UpdateCurrencyFormat überschrieben werden müssen –
|
||||||
|
' für Formel-Spalten (kein ColumnEdit) greift aber nur DisplayFormat,
|
||||||
|
' weshalb ein falscher Initialwert hier persistent bleibt.
|
||||||
|
_Logger.Debug("CURRENCY column [{0}]: DisplayFormat wird von ConfigureViewColumnsCurrency gesetzt", oCol.FieldName)
|
||||||
|
|
||||||
End Select
|
End Select
|
||||||
|
|
||||||
@@ -266,15 +403,16 @@ Namespace ControlCreator
|
|||||||
Select Case oSummaryFunction
|
Select Case oSummaryFunction
|
||||||
Case Constants.AGGREGATE_TOTAL_INTEGER
|
Case Constants.AGGREGATE_TOTAL_INTEGER
|
||||||
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
||||||
oCol.SummaryItem.DisplayFormat = "SUM: {0:N0}"
|
oCol.SummaryItem.DisplayFormat = "{0:N0}"
|
||||||
oShouldDisplayFooter = True
|
oShouldDisplayFooter = True
|
||||||
|
|
||||||
Case Constants.AGGREGATE_TOTAL_FLOAT
|
Case Constants.AGGREGATE_TOTAL_FLOAT
|
||||||
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
oCol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum
|
||||||
oCol.SummaryItem.DisplayFormat = "SUM: {0:N2}"
|
oCol.SummaryItem.DisplayFormat = "{0:N2}"
|
||||||
oShouldDisplayFooter = True
|
oShouldDisplayFooter = True
|
||||||
|
|
||||||
Case Constants.AGGREGATE_TOTAL_CURRENCY
|
Case Constants.AGGREGATE_TOTAL_CURRENCY
|
||||||
|
_Logger.Debug(Of String)("Applying currency summary format for column [{0}]", oCol.FieldName)
|
||||||
ApplyCurrencySummaryFormat(oCol)
|
ApplyCurrencySummaryFormat(oCol)
|
||||||
oShouldDisplayFooter = True
|
oShouldDisplayFooter = True
|
||||||
|
|
||||||
@@ -311,49 +449,140 @@ Namespace ControlCreator
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Public Sub ConfigureViewColumnsCurrency(pColumnTable As DataTable, pGridView As GridView, pGrid As DevExpress.XtraGrid.GridControl)
|
Public Sub ConfigureViewColumnsCurrency(pColumnTable As DataTable, pGridView As GridView, pGrid As DevExpress.XtraGrid.GridControl)
|
||||||
|
|
||||||
Dim oCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
Dim oCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
||||||
oCultureInfo.NumberFormat.CurrencySymbol = _currencySymbol
|
oCultureInfo.NumberFormat.CurrencySymbol = _currencySymbol
|
||||||
|
|
||||||
Dim riTextEdit As RepositoryItemTextEdit = New RepositoryItemTextEdit()
|
Dim riTextEdit As RepositoryItemTextEdit = New RepositoryItemTextEdit()
|
||||||
riTextEdit.MaskSettings.Configure(Of MaskSettings.Numeric)(Sub(settings)
|
riTextEdit.MaskSettings.Configure(Of MaskSettings.Numeric)(
|
||||||
|
Sub(settings)
|
||||||
settings.MaskExpression = "c"
|
settings.MaskExpression = "c"
|
||||||
settings.Culture = oCultureInfo
|
settings.Culture = oCultureInfo
|
||||||
End Sub)
|
End Sub)
|
||||||
riTextEdit.UseMaskAsDisplayFormat = True
|
riTextEdit.UseMaskAsDisplayFormat = False
|
||||||
pGrid.RepositoryItems.Add(riTextEdit)
|
riTextEdit.DisplayFormat.FormatType = FormatType.Custom
|
||||||
|
riTextEdit.DisplayFormat.FormatString = $"#,##0.00 {_currencySymbol}"
|
||||||
|
|
||||||
|
' *** DIAGNOSE 1: Zustand der RepositoryItems VOR der Zuweisung ***
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] riTextEdit erstellt: DisplayFormat=[{0}], HashCode=[{1}]",
|
||||||
|
riTextEdit.DisplayFormat.FormatString, riTextEdit.GetHashCode())
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] pGrid.RepositoryItems.Count VOR Schleife=[{0}]",
|
||||||
|
pGrid.RepositoryItems.Count)
|
||||||
|
|
||||||
For Each oCol As GridColumn In pGridView.Columns
|
For Each oCol As GridColumn In pGridView.Columns
|
||||||
Dim oColumnData As DataRow = pColumnTable.
|
Dim oColumnData As DataRow = pColumnTable.
|
||||||
Select($"SPALTENNAME = '{oCol.FieldName}'").
|
Select($"SPALTENNAME = '{oCol.FieldName}'").
|
||||||
FirstOrDefault()
|
FirstOrDefault()
|
||||||
|
If oColumnData Is Nothing Then Continue For
|
||||||
|
|
||||||
If oColumnData Is Nothing Then
|
Dim oColumnType As String = ObjectEx.NotNull(oColumnData.Item("TYPE_COLUMN"), String.Empty).ToString()
|
||||||
Continue For
|
If oColumnType <> "CURRENCY" Then Continue For
|
||||||
End If
|
|
||||||
|
|
||||||
' *** NEU: Prüfe ob Spalte editierbar ist ***
|
|
||||||
If Not oCol.OptionsColumn.AllowEdit Then
|
|
||||||
_Logger.Debug("Skipping ColumnEdit for read-only column [{0}]", oCol.FieldName)
|
|
||||||
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)
|
Dim oFormulaExpression = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty)
|
||||||
If oFormulaExpression <> String.Empty Then
|
Dim oIsFormula As Boolean = oFormulaExpression <> String.Empty
|
||||||
_Logger.Debug("Skipping ColumnEdit assignment for formula column [{0}] – using DisplayFormat only.", oCol.FieldName)
|
|
||||||
Continue For
|
If oIsFormula Then
|
||||||
|
oCol.DisplayFormat.FormatType = FormatType.Custom
|
||||||
|
oCol.DisplayFormat.FormatString = $"#,##0.00 {_currencySymbol}"
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] Formel-Spalte [{0}]: DisplayFormat=[{1}], RepositoryItems.Count=[{2}]",
|
||||||
|
oCol.FieldName, oCol.DisplayFormat.FormatString, pGrid.RepositoryItems.Count)
|
||||||
|
|
||||||
|
ElseIf oCol.OptionsColumn.AllowEdit Then
|
||||||
|
' *** DIAGNOSE 2: RepositoryItems-Count VOR und NACH ColumnEdit-Zuweisung ***
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] [{0}] VOR ColumnEdit: RepositoryItems.Count=[{1}]",
|
||||||
|
oCol.FieldName, pGrid.RepositoryItems.Count)
|
||||||
|
|
||||||
|
oCol.ColumnEdit = riTextEdit
|
||||||
|
|
||||||
|
' *** DIAGNOSE 3: Prüfen ob DevExpress das Item intern zu RepositoryItems hinzugefügt hat ***
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] [{0}] NACH ColumnEdit: RepositoryItems.Count=[{1}]",
|
||||||
|
oCol.FieldName, pGrid.RepositoryItems.Count)
|
||||||
|
|
||||||
|
Dim assignedEdit = TryCast(oCol.ColumnEdit, RepositoryItemTextEdit)
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] [{0}]: IsSameObject=[{1}], ColumnEdit.DisplayFormat=[{2}], ColumnEdit.HashCode=[{3}]",
|
||||||
|
oCol.FieldName,
|
||||||
|
Object.ReferenceEquals(assignedEdit, riTextEdit),
|
||||||
|
If(assignedEdit IsNot Nothing, assignedEdit.DisplayFormat.FormatString, "N/A"),
|
||||||
|
If(assignedEdit IsNot Nothing, assignedEdit.GetHashCode(), -1))
|
||||||
|
|
||||||
|
' *** DIAGNOSE 4: Alle Items in RepositoryItems ausgeben ***
|
||||||
|
For i As Integer = 0 To pGrid.RepositoryItems.Count - 1
|
||||||
|
_Logger.Debug("[ConfigureViewColumnsCurrency] RepositoryItems[{0}]: Type=[{1}], HashCode=[{2}]",
|
||||||
|
i, pGrid.RepositoryItems(i).GetType().Name, pGrid.RepositoryItems(i).GetHashCode())
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
' *** DIAGNOSE 5: CustomColumnDisplayText – feuert es überhaupt? ***
|
||||||
|
' Temporär direkt hier einen einmaligen Test-Handler registrieren
|
||||||
|
Dim oTestFired As Boolean = False
|
||||||
|
AddHandler pGridView.CustomColumnDisplayText,
|
||||||
|
Sub(sender As Object, e As CustomColumnDisplayTextEventArgs)
|
||||||
|
If e.Column Is Nothing OrElse e.Value Is Nothing OrElse IsDBNull(e.Value) Then
|
||||||
|
Return
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Dim oColumnType As String = oColumnData.Item("TYPE_COLUMN")
|
' Prüfe ob Spalte vom Typ CURRENCY ist
|
||||||
|
Dim oColumnData As DataRow = pColumnTable.
|
||||||
|
Select($"SPALTENNAME = '{e.Column.FieldName}'").
|
||||||
|
FirstOrDefault()
|
||||||
|
|
||||||
Select Case oColumnType
|
If oColumnData IsNot Nothing AndAlso
|
||||||
Case "CURRENCY"
|
oColumnData.Item("TYPE_COLUMN").ToString() = "CURRENCY" Then
|
||||||
' *** WICHTIG: NUR ColumnEdit setzen, KEIN DisplayFormat mehr! ***
|
|
||||||
oCol.ColumnEdit = riTextEdit
|
Try
|
||||||
End Select
|
' *** KERN-FIX: Hole Symbol aus SHARED Dictionary statt Instanz-Feld ***
|
||||||
Next
|
Dim currentSymbol As String = _currencySymbol ' Fallback
|
||||||
|
Dim gridName As String = pGrid.Name ' <-- FIX: pGrid statt pControl
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
If _CurrencySymbolByGridName.ContainsKey(gridName) Then
|
||||||
|
currentSymbol = _CurrencySymbolByGridName(gridName)
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
|
||||||
|
Dim oValue As Double
|
||||||
|
' *** KRITISCH: Robustes Parsing unabhängig vom Dezimaltrenner ***
|
||||||
|
If TypeOf e.Value Is Double OrElse TypeOf e.Value Is Decimal Then
|
||||||
|
oValue = Convert.ToDouble(e.Value)
|
||||||
|
ElseIf TypeOf e.Value Is String Then
|
||||||
|
Dim oStringValue As String = e.Value.ToString().Trim()
|
||||||
|
|
||||||
|
' Versuche zuerst deutsches Format (1.234,56)
|
||||||
|
Dim oDeCulture As CultureInfo = New CultureInfo("de-DE")
|
||||||
|
If Double.TryParse(oStringValue, NumberStyles.Currency Or NumberStyles.Number, oDeCulture, oValue) Then
|
||||||
|
' Erfolgreich mit deutschem Format geparst
|
||||||
|
ElseIf Double.TryParse(oStringValue, NumberStyles.Currency Or NumberStyles.Number, CultureInfo.InvariantCulture, oValue) Then
|
||||||
|
' Erfolgreich mit invariantem Format (Punkt als Dezimaltrenner)
|
||||||
|
Else
|
||||||
|
' Fallback: Systemkultur
|
||||||
|
oValue = Convert.ToDouble(oStringValue, CultureInfo.CurrentCulture)
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
oValue = Convert.ToDouble(e.Value)
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Formatierung IMMER mit deutscher Kultur (Komma als Dezimaltrenner)
|
||||||
|
Dim oDeCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
||||||
|
e.DisplayText = oValue.ToString("N2", oDeCultureInfo) & " " & currentSymbol
|
||||||
|
|
||||||
|
_Logger.Debug("[CustomColumnDisplayText] CURRENCY [{0}]: DisplayText=[{1}], Symbol=[{2}] (from Shared Dict in ConfigureViewColumnsCurrency)",
|
||||||
|
e.Column.FieldName, e.DisplayText, currentSymbol)
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
_Logger.Warn("⚠️ Could not format currency value [{0}] for column [{1}]: {2}",
|
||||||
|
e.Value, e.Column.FieldName, ex.Message)
|
||||||
|
' Fallback: Original-Wert + Symbol
|
||||||
|
Dim fallbackSymbol As String = _currencySymbol
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
If _CurrencySymbolByGridName.ContainsKey(pGrid.Name) Then ' <-- FIX: pGrid statt pControl
|
||||||
|
fallbackSymbol = _CurrencySymbolByGridName(pGrid.Name)
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
e.DisplayText = e.Value.ToString() & " " & fallbackSymbol
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
End Sub
|
||||||
|
|
||||||
Public Sub ConfigureViewEvents(pColumnTable As DataTable, pGridView As GridView, pControl As Windows.Forms.Control, pControlId As Integer)
|
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
|
' Formel-Spalten-Namen einmalig cachen für View_ShowingEditor
|
||||||
_FormulaColumnNames.Clear()
|
_FormulaColumnNames.Clear()
|
||||||
@@ -405,6 +634,15 @@ Namespace ControlCreator
|
|||||||
oColumnData.Item("TYPE_COLUMN").ToString() = "CURRENCY" Then
|
oColumnData.Item("TYPE_COLUMN").ToString() = "CURRENCY" Then
|
||||||
|
|
||||||
Try
|
Try
|
||||||
|
' *** KERN-FIX: Hole Symbol aus SHARED Dictionary statt Instanz-Feld ***
|
||||||
|
Dim currentSymbol As String = _currencySymbol ' Fallback
|
||||||
|
Dim gridName As String = pControl.Name
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
If _CurrencySymbolByGridName.ContainsKey(gridName) Then
|
||||||
|
currentSymbol = _CurrencySymbolByGridName(gridName)
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
|
||||||
Dim oValue As Double
|
Dim oValue As Double
|
||||||
' *** KRITISCH: Robustes Parsing unabhängig vom Dezimaltrenner ***
|
' *** KRITISCH: Robustes Parsing unabhängig vom Dezimaltrenner ***
|
||||||
If TypeOf e.Value Is Double OrElse TypeOf e.Value Is Decimal Then
|
If TypeOf e.Value Is Double OrElse TypeOf e.Value Is Decimal Then
|
||||||
@@ -428,13 +666,22 @@ Namespace ControlCreator
|
|||||||
|
|
||||||
' Formatierung IMMER mit deutscher Kultur (Komma als Dezimaltrenner)
|
' Formatierung IMMER mit deutscher Kultur (Komma als Dezimaltrenner)
|
||||||
Dim oDeCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
Dim oDeCultureInfo As CultureInfo = New CultureInfo("de-DE")
|
||||||
e.DisplayText = oValue.ToString("N2", oDeCultureInfo) & " " & _currencySymbol
|
e.DisplayText = oValue.ToString("N2", oDeCultureInfo) & " " & currentSymbol
|
||||||
|
|
||||||
|
_Logger.Debug("[CustomColumnDisplayText] CURRENCY [{0}]: DisplayText=[{1}], Symbol=[{2}] (from Shared Dict in ConfigureViewEvents)",
|
||||||
|
e.Column.FieldName, e.DisplayText, currentSymbol)
|
||||||
|
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
_Logger.Warn("⚠️ Could not format currency value [{0}] for column [{1}]: {2}",
|
_Logger.Warn("⚠️ Could not format currency value [{0}] for column [{1}]: {2}",
|
||||||
e.Value, e.Column.FieldName, ex.Message)
|
e.Value, e.Column.FieldName, ex.Message)
|
||||||
' Fallback: Original-Wert + Symbol
|
' Fallback: Original-Wert + Symbol
|
||||||
e.DisplayText = e.Value.ToString() & " " & _currencySymbol
|
Dim fallbackSymbol As String = _currencySymbol
|
||||||
|
SyncLock _CurrencySymbolByGridName
|
||||||
|
If _CurrencySymbolByGridName.ContainsKey(pControl.Name) Then
|
||||||
|
fallbackSymbol = _CurrencySymbolByGridName(pControl.Name)
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
e.DisplayText = e.Value.ToString() & " " & fallbackSymbol
|
||||||
End Try
|
End Try
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -442,19 +689,47 @@ Namespace ControlCreator
|
|||||||
AddHandler pGridView.CustomRowCellEdit, Sub(sender As Object, e As CustomRowCellEditEventArgs)
|
AddHandler pGridView.CustomRowCellEdit, Sub(sender As Object, e As CustomRowCellEditEventArgs)
|
||||||
Try
|
Try
|
||||||
For Each oRow As DataRow In pColumnTable.Rows
|
For Each oRow As DataRow In pColumnTable.Rows
|
||||||
Dim oColumnName = oRow.Item("SPALTENNAME")
|
Dim oColumnName As String = oRow.Item("SPALTENNAME").ToString()
|
||||||
|
If oColumnName <> e.Column.FieldName Then Continue For
|
||||||
|
|
||||||
Dim oEditorExists = GridTables_TestEditorExistsByControlAndColumn(pControlId, oColumnName)
|
Dim oEditorExists = GridTables_TestEditorExistsByControlAndColumn(pControlId, oColumnName)
|
||||||
If oColumnName <> e.Column.FieldName Then
|
|
||||||
Continue For
|
|
||||||
End If
|
|
||||||
|
|
||||||
If oEditorExists Then
|
If oEditorExists Then
|
||||||
|
' Combobox/Lookup-Editor aus GridTables: immer zuweisen
|
||||||
Dim oEditor = _GridTables.Item(pControlId).Item(oColumnName)
|
Dim oEditor = _GridTables.Item(pControlId).Item(oColumnName)
|
||||||
_Logger.Debug("Assigning Editor to Column [{0}]", oColumnName)
|
_Logger.Debug("Assigning Editor to Column [{0}]", oColumnName)
|
||||||
e.RepositoryItem = oEditor
|
e.RepositoryItem = oEditor
|
||||||
|
Else
|
||||||
|
Dim oColumnType As String = ObjectEx.NotNull(oRow.Item("TYPE_COLUMN"), String.Empty).ToString()
|
||||||
|
If oColumnType = "CURRENCY" Then
|
||||||
|
' *** KERN-FIX ***
|
||||||
|
' Für CURRENCY-Spalten wird e.RepositoryItem NIEMALS gesetzt.
|
||||||
|
'
|
||||||
|
' Grund: Sobald e.RepositoryItem gesetzt ist, übernimmt das
|
||||||
|
' RepositoryItem die komplette Zelldarstellung – DevExpress
|
||||||
|
' übergeht CustomColumnDisplayText vollständig. Das RepositoryItem
|
||||||
|
' verwendet intern die Mask-Culture ("c" = EUR) zur Anzeige,
|
||||||
|
' unabhängig von DisplayFormat oder _currencySymbol.
|
||||||
|
'
|
||||||
|
' Korrekte Architektur:
|
||||||
|
' - Anzeige (nicht editiert): CustomColumnDisplayText
|
||||||
|
' → formatiert mit _currencySymbol (CHF)
|
||||||
|
' - Bearbeitung (editiert): ColumnEdit an der GridColumn
|
||||||
|
' → wird von DevExpress beim Öffnen
|
||||||
|
' des Editors automatisch verwendet
|
||||||
|
'
|
||||||
|
' CustomRowCellEdit muss NICHT eingreifen – GridColumn.ColumnEdit
|
||||||
|
' ist bereits gesetzt und wird für den Editiermodus korrekt genutzt.
|
||||||
|
If _FormulaColumnNames.Contains(oColumnName) Then
|
||||||
|
_Logger.Debug("CURRENCY column [{0}] is formula/readonly – CustomColumnDisplayText handles display", oColumnName)
|
||||||
|
Else
|
||||||
|
_Logger.Debug("CURRENCY column [{0}] – NO e.RepositoryItem set. Display via CustomColumnDisplayText, Edit via GridColumn.ColumnEdit", oColumnName)
|
||||||
|
End If
|
||||||
Else
|
Else
|
||||||
_Logger.Debug("Editor for Column [{0}] does not exist", oColumnName)
|
_Logger.Debug("Editor for Column [{0}] does not exist", oColumnName)
|
||||||
End If
|
End If
|
||||||
|
End If
|
||||||
|
Exit For
|
||||||
Next
|
Next
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
_Logger.Warn("⚠️ Error in CustomRowCellEdit for [{0}]", e.CellValue)
|
_Logger.Warn("⚠️ Error in CustomRowCellEdit for [{0}]", e.CellValue)
|
||||||
|
|||||||
1804
app/TaskFlow/Log_Waehrung.txt
Normal file
1804
app/TaskFlow/Log_Waehrung.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
|||||||
' übernehmen, indem Sie "*" eingeben:
|
' übernehmen, indem Sie "*" eingeben:
|
||||||
' <Assembly: AssemblyVersion("1.0.*")>
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
<Assembly: AssemblyVersion("2.8.4.0")>
|
<Assembly: AssemblyVersion("2.8.5.0")>
|
||||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("")>
|
<Assembly: NeutralResourcesLanguage("")>
|
||||||
|
|||||||
@@ -1284,6 +1284,7 @@
|
|||||||
<Content Include="DataColumnExpression.txt" />
|
<Content Include="DataColumnExpression.txt" />
|
||||||
<Content Include="DD_Icons_ICO_PMANAGER_48px.ico" />
|
<Content Include="DD_Icons_ICO_PMANAGER_48px.ico" />
|
||||||
<Content Include="DD_taskFLOW_ICON.ico" />
|
<Content Include="DD_taskFLOW_ICON.ico" />
|
||||||
|
<Content Include="Log_Waehrung.txt" />
|
||||||
<Content Include="MailLicense.xml">
|
<Content Include="MailLicense.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
Imports System.Text.RegularExpressions
|
Imports System.Text.RegularExpressions
|
||||||
Imports WINDREAMLib
|
Imports DevExpress.Xpo.Helpers.AssociatedCollectionCriteriaHelper
|
||||||
Imports DigitalData.Controls.LookupGrid
|
|
||||||
Imports DevExpress.XtraGrid
|
|
||||||
Imports DevExpress.XtraGrid.Views.Grid
|
|
||||||
Imports DevExpress.XtraGrid.Columns
|
|
||||||
Imports DevExpress.XtraEditors
|
Imports DevExpress.XtraEditors
|
||||||
|
Imports DevExpress.XtraGrid
|
||||||
|
Imports DevExpress.XtraGrid.Columns
|
||||||
|
Imports DevExpress.XtraGrid.Views.Grid
|
||||||
|
Imports DigitalData.Controls.LookupGrid
|
||||||
|
Imports WINDREAMLib
|
||||||
''' <summary>
|
''' <summary>
|
||||||
''' Defines common Functions for Checking for and replacing placeholders.
|
''' Defines common Functions for Checking for and replacing placeholders.
|
||||||
''' This Class also includes a child class `Pattern` for passing around Patterns.
|
''' This Class also includes a child class `Pattern` for passing around Patterns.
|
||||||
@@ -150,34 +151,39 @@ Public Class clsPatterns
|
|||||||
End Function
|
End Function
|
||||||
|
|
||||||
Public Shared Function ReplaceAllValues(input As String, panel As DevExpress.XtraEditors.XtraScrollableControl, is_SQL As Boolean) As String
|
Public Shared Function ReplaceAllValues(input As String, panel As DevExpress.XtraEditors.XtraScrollableControl, is_SQL As Boolean) As String
|
||||||
|
Dim oResult = input
|
||||||
Try
|
Try
|
||||||
Dim result = input
|
|
||||||
|
|
||||||
If Not HasAnyPatterns(result) Then
|
If Not HasAnyPatterns(oResult) Then
|
||||||
Return result
|
Return oResult
|
||||||
End If
|
End If
|
||||||
|
|
||||||
LOGGER.Debug($"input BEFORE replacing: [{result}]")
|
LOGGER.Debug($"input BEFORE replacing: [{oResult}]")
|
||||||
result = ReplaceInternalValues(result)
|
oResult = ReplaceInternalValues(oResult)
|
||||||
|
|
||||||
If Not IsNothing(CURRENT_WMFILE) Then
|
If Not IsNothing(CURRENT_WMFILE) Then
|
||||||
result = ReplaceWindreamIndicies(result, CURRENT_WMFILE, is_SQL)
|
oResult = ReplaceWindreamIndicies(oResult, CURRENT_WMFILE, is_SQL)
|
||||||
End If
|
End If
|
||||||
If IDB_ACTIVE = True Then
|
If IDB_ACTIVE = True Then
|
||||||
result = ReplaceIDBAttributes(result, is_SQL)
|
oResult = ReplaceIDBAttributes(oResult, is_SQL)
|
||||||
End If
|
End If
|
||||||
'vorher hinter result = ReplaceInternalValues(result)
|
'vorher hinter result = ReplaceInternalValues(result)
|
||||||
result = ReplaceControlValues(result, panel, is_SQL)
|
oResult = ReplaceControlValues(oResult, panel, is_SQL)
|
||||||
|
|
||||||
If Not IsNothing(result) Then
|
If Not IsNothing(oResult) Then
|
||||||
result = ReplaceUserValues(result)
|
oResult = ReplaceUserValues(oResult)
|
||||||
LOGGER.Debug($"input AFTER replacing: [{result}]")
|
LOGGER.Debug($"input AFTER replacing: [{oResult}]")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
Return result
|
Return oResult
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
LOGGER.Error(ex)
|
LOGGER.Error(ex)
|
||||||
LOGGER.Info("Error in ReplaceAllValues:" & ex.Message)
|
LOGGER.Error($"❌ CRITICAL ERROR in ReplaceAllValues!")
|
||||||
|
LOGGER.Error($" Input: [{input}]")
|
||||||
|
LOGGER.Error($" Last successful result: [{oResult}]")
|
||||||
|
LOGGER.Error($" Exception Type: [{ex.GetType().Name}]")
|
||||||
|
LOGGER.Error($" Message: [{ex.Message}]")
|
||||||
|
LOGGER.Error($" StackTrace: [{ex.StackTrace}]")
|
||||||
Return input
|
Return input
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
@@ -354,12 +360,28 @@ Public Class clsPatterns
|
|||||||
Case GetType(LookupControl3)
|
Case GetType(LookupControl3)
|
||||||
Dim oLookupControl3 As LookupControl3 = oControl
|
Dim oLookupControl3 As LookupControl3 = oControl
|
||||||
|
|
||||||
If oLookupControl3.Properties.SelectedValues.Count > 1 Then
|
|
||||||
LOGGER.Debug($"LookupControl3 mit mehr als 1 Value")
|
|
||||||
Dim oIndex As Integer = 0
|
|
||||||
For Each oString As String In oLookupControl3.Properties.SelectedValues
|
|
||||||
If oIndex = 0 Then
|
|
||||||
|
|
||||||
|
' ========== FIX START: NULL-Check ==========
|
||||||
|
Dim selectedValues As List(Of String) = Nothing
|
||||||
|
Try
|
||||||
|
selectedValues = oLookupControl3.Properties.SelectedValues
|
||||||
|
Catch ex As Exception
|
||||||
|
LOGGER.Warn($"⚠️ LookupControl [{oControlName}] SelectedValues not accessible: {ex.Message}")
|
||||||
|
selectedValues = Nothing
|
||||||
|
End Try
|
||||||
|
|
||||||
|
If selectedValues Is Nothing Then
|
||||||
|
LOGGER.Warn($"⚠️ LookupControl [{oControlName}] SelectedValues is Nothing! Using ERROR_REPLACE_VALUE")
|
||||||
|
oReplaceValue = ERROR_REPLACE_VALUE
|
||||||
|
ElseIf selectedValues.Count = 0 Then
|
||||||
|
LOGGER.Warn($"⚠️ LookupControl [{oControlName}] SelectedValues is empty! Using ERROR_REPLACE_VALUE")
|
||||||
|
oReplaceValue = ERROR_REPLACE_VALUE
|
||||||
|
' ========== FIX END ==========
|
||||||
|
ElseIf selectedValues.Count > 1 Then
|
||||||
|
LOGGER.Debug($"LookupControl3 [{oControlName}] mit mehr als 1 Value")
|
||||||
|
Dim oIndex As Integer = 0
|
||||||
|
For Each oString As String In selectedValues
|
||||||
|
If oIndex = 0 Then
|
||||||
oReplaceValue = oString
|
oReplaceValue = oString
|
||||||
Else
|
Else
|
||||||
oReplaceValue += "', '" + oString
|
oReplaceValue += "', '" + oString
|
||||||
@@ -367,13 +389,12 @@ Public Class clsPatterns
|
|||||||
oIndex += 1
|
oIndex += 1
|
||||||
Next
|
Next
|
||||||
oIsSQL = False
|
oIsSQL = False
|
||||||
ElseIf oLookupControl3.Properties.SelectedValues.Count = 1 Then
|
Else ' Count = 1
|
||||||
LOGGER.Debug($"LookupControl3 mit genau einem Value")
|
LOGGER.Debug($"LookupControl3 [{oControlName}] mit genau einem Value")
|
||||||
oReplaceValue = oLookupControl3.Properties.SelectedValues(0)
|
oReplaceValue = selectedValues(0)
|
||||||
Else
|
|
||||||
' LOGGER.Warn($"SelectedValues of LookUpControl scheint empty oder leer zu sein! Ersetzen mit ErrorReplaceValue!")
|
|
||||||
oReplaceValue = ERROR_REPLACE_VALUE
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
LOGGER.Debug($"oReplaceValue nach Durchlaufen selectedValues: {oReplaceValue}")
|
||||||
LOGGER.Debug($"oReplaceValue nach Durchlaufen selectedValues: {oReplaceValue}")
|
LOGGER.Debug($"oReplaceValue nach Durchlaufen selectedValues: {oReplaceValue}")
|
||||||
|
|
||||||
Case GetType(Windows.Forms.ComboBox)
|
Case GetType(Windows.Forms.ComboBox)
|
||||||
@@ -381,7 +402,7 @@ Public Class clsPatterns
|
|||||||
|
|
||||||
Case GetType(CheckBox)
|
Case GetType(CheckBox)
|
||||||
Dim oCheckBox As CheckBox = oControl
|
Dim oCheckBox As CheckBox = oControl
|
||||||
oReplaceValue = oCheckBox.Checked
|
oReplaceValue = If(oCheckBox.Checked, "1", "0") ' Explizite String-Konvertierung
|
||||||
|
|
||||||
Case GetType(GridControl)
|
Case GetType(GridControl)
|
||||||
Dim oGrid As GridControl = oControl
|
Dim oGrid As GridControl = oControl
|
||||||
@@ -406,10 +427,18 @@ Public Class clsPatterns
|
|||||||
Case Else
|
Case Else
|
||||||
oReplaceValue = ERROR_REPLACE_VALUE
|
oReplaceValue = ERROR_REPLACE_VALUE
|
||||||
End Select
|
End Select
|
||||||
|
LOGGER.Debug($"[SQL-ESCAPE CHECK] Control: [{oControlName}], oReplaceValue Type: [{If(oReplaceValue?.GetType()?.Name, "NULL")}], Value: [{oReplaceValue}], IsSQL: [{oIsSQL}]")
|
||||||
|
If oReplaceValue Is Nothing Then
|
||||||
|
LOGGER.Warn($"⚠️ oReplaceValue is Nothing for control [{oControlName}]! Setting to ERROR_REPLACE_VALUE")
|
||||||
|
oReplaceValue = ERROR_REPLACE_VALUE
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not TypeOf oReplaceValue Is String Then
|
||||||
|
LOGGER.Warn($"⚠️ oReplaceValue is not a String for control [{oControlName}]! Type: [{oReplaceValue.GetType().Name}]. Converting to String.")
|
||||||
|
oReplaceValue = oReplaceValue.ToString()
|
||||||
|
End If
|
||||||
If oIsSQL = True Then
|
If oIsSQL = True Then
|
||||||
'LOGGER.Debug($"IS_SQL = True - oReplaceValue = {oReplaceValue}")
|
oReplaceValue = SafeSqlEscape(oReplaceValue)
|
||||||
'LOGGER.Debug($"oReplaceValue = {oReplaceValue}")
|
|
||||||
oReplaceValue = oReplaceValue.Replace("'", "''")
|
|
||||||
End If
|
End If
|
||||||
oResult = ReplacePattern(oResult, PATTERN_CTRL, oReplaceValue)
|
oResult = ReplacePattern(oResult, PATTERN_CTRL, oReplaceValue)
|
||||||
Else
|
Else
|
||||||
@@ -425,16 +454,46 @@ Public Class clsPatterns
|
|||||||
Return oResult
|
Return oResult
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
|
Private Shared Function SafeSqlEscape(value As Object) As String
|
||||||
|
LOGGER.Debug($"[SafeSqlEscape] Input Type: [{If(value?.GetType()?.Name, "NULL")}], Value: [{value}]")
|
||||||
|
|
||||||
|
If value Is Nothing Then
|
||||||
|
LOGGER.Warn("[SafeSqlEscape] Value is Nothing → returning ERROR_REPLACE_VALUE")
|
||||||
|
Return ERROR_REPLACE_VALUE
|
||||||
|
End If
|
||||||
|
|
||||||
|
Dim strValue As String
|
||||||
|
Try
|
||||||
|
strValue = value.ToString()
|
||||||
|
Catch ex As Exception
|
||||||
|
LOGGER.Error(ex)
|
||||||
|
LOGGER.Warn($"[SafeSqlEscape] ToString() failed: {ex.Message} → returning ERROR_REPLACE_VALUE")
|
||||||
|
Return ERROR_REPLACE_VALUE
|
||||||
|
End Try
|
||||||
|
|
||||||
|
If String.IsNullOrEmpty(strValue) Then
|
||||||
|
LOGGER.Warn("[SafeSqlEscape] String is empty → returning ERROR_REPLACE_VALUE")
|
||||||
|
Return ERROR_REPLACE_VALUE
|
||||||
|
End If
|
||||||
|
|
||||||
|
Dim escaped = strValue.Replace("'", "''")
|
||||||
|
LOGGER.Debug($"[SafeSqlEscape] Output: [{escaped}]")
|
||||||
|
Return escaped
|
||||||
|
End Function
|
||||||
Public Shared Function ReplaceWindreamIndicies(pInput As String, pDocument As WMObject, pIsSQL As Boolean) As String
|
Public Shared Function ReplaceWindreamIndicies(pInput As String, pDocument As WMObject, pIsSQL As Boolean) As String
|
||||||
Try
|
Try
|
||||||
Dim oResult = pInput
|
Dim oResult = pInput
|
||||||
Dim oTryCounter As Integer = 0
|
Dim oTryCounter As Integer = 0
|
||||||
|
|
||||||
While ContainsPattern(oResult, PATTERN_WMI)
|
While ContainsPattern(oResult, PATTERN_WMI)
|
||||||
|
Dim oWMValue As String
|
||||||
Dim oIndexName As String = GetNextPattern(oResult, PATTERN_WMI).Value
|
Dim oIndexName As String = GetNextPattern(oResult, PATTERN_WMI).Value
|
||||||
Dim oWMValue As String = pDocument.GetVariableValue(oIndexName)
|
If oIndexName = "@@DISPLAY_ONLY" Then
|
||||||
|
oWMValue = String.Empty
|
||||||
|
Else
|
||||||
|
oWMValue = pDocument.GetVariableValue(oIndexName)
|
||||||
|
End If
|
||||||
|
|
||||||
|
|
||||||
If IsNothing(oWMValue) And oTryCounter = MAX_TRY_COUNT Then
|
If IsNothing(oWMValue) And oTryCounter = MAX_TRY_COUNT Then
|
||||||
Throw New Exception("Max tries in ReplaceWindreamIndicies exceeded.")
|
Throw New Exception("Max tries in ReplaceWindreamIndicies exceeded.")
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw
|
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADw
|
||||||
CAAAAk1TRnQBSQFMAgEBAgEAAfABCwHwAQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
CAAAAk1TRnQBSQFMAgEBAgEAAfgBCwH4AQsBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||||
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
||||||
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
||||||
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
||||||
@@ -1506,13 +1506,13 @@
|
|||||||
<value>Aktionen</value>
|
<value>Aktionen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RibbonControl1.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="RibbonControl1.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>1178, 158</value>
|
<value>1178, 126</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RibbonStatusBar1.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="RibbonStatusBar1.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>0, 666</value>
|
<value>0, 670</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RibbonStatusBar1.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="RibbonStatusBar1.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>1178, 22</value>
|
<value>1178, 18</value>
|
||||||
</data>
|
</data>
|
||||||
<data name=">>RibbonStatusBar1.Name" xml:space="preserve">
|
<data name=">>RibbonStatusBar1.Name" xml:space="preserve">
|
||||||
<value>RibbonStatusBar1</value>
|
<value>RibbonStatusBar1</value>
|
||||||
@@ -1539,7 +1539,7 @@
|
|||||||
<value>4</value>
|
<value>4</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GridControlWorkflows.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="GridControlWorkflows.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>945, 484</value>
|
<value>945, 549</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GridControlWorkflows.TabIndex" type="System.Int32, mscorlib">
|
<data name="GridControlWorkflows.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>10</value>
|
<value>10</value>
|
||||||
@@ -1782,7 +1782,7 @@
|
|||||||
<value>233</value>
|
<value>233</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NavBarControl1.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="NavBarControl1.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>233, 508</value>
|
<value>233, 573</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NavBarControl1.TabIndex" type="System.Int32, mscorlib">
|
<data name="NavBarControl1.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>5</value>
|
<value>5</value>
|
||||||
@@ -1809,10 +1809,10 @@
|
|||||||
<value>Tahoma, 9pt</value>
|
<value>Tahoma, 9pt</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Panel1.Location" type="System.Drawing.Point, System.Drawing">
|
<data name="Panel1.Location" type="System.Drawing.Point, System.Drawing">
|
||||||
<value>0, 158</value>
|
<value>0, 101</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Panel1.Size" type="System.Drawing.Size, System.Drawing">
|
<data name="Panel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>1178, 508</value>
|
<value>1178, 573</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Panel1.TabIndex" type="System.Int32, mscorlib">
|
<data name="Panel1.TabIndex" type="System.Int32, mscorlib">
|
||||||
<value>4</value>
|
<value>4</value>
|
||||||
@@ -2111,7 +2111,7 @@
|
|||||||
<value>9, 19</value>
|
<value>9, 19</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
|
||||||
<value>1178, 688</value>
|
<value>1473, 860</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.Font" type="System.Drawing.Font, System.Drawing">
|
<data name="$this.Font" type="System.Drawing.Font, System.Drawing">
|
||||||
<value>Tahoma, 12pt</value>
|
<value>Tahoma, 12pt</value>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -468,7 +468,55 @@ Public Class frmValidatorSearch
|
|||||||
ToolStripDropDownButtonFile.Visible = False
|
ToolStripDropDownButtonFile.Visible = False
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Sub EnsureFormIsVisible()
|
||||||
|
Try
|
||||||
|
' Aktuellen Bildschirm basierend auf der Formularposition ermitteln
|
||||||
|
Dim currentScreen As Screen = Screen.FromPoint(Me.Location)
|
||||||
|
Dim workingArea As Rectangle = currentScreen.WorkingArea
|
||||||
|
|
||||||
|
' Prüfen ob das Formular vollständig außerhalb des sichtbaren Bereichs liegt
|
||||||
|
Dim formBounds As New Rectangle(Me.Location, Me.Size)
|
||||||
|
|
||||||
|
' Wenn das Formular nicht mit dem Arbeitsbereich überschneidet
|
||||||
|
If Not workingArea.IntersectsWith(formBounds) Then
|
||||||
|
CenterFormOnScreen()
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Optional: Prüfen ob das Formular zu weit außerhalb liegt (z.B. nur 20% sichtbar)
|
||||||
|
Dim visibleArea As Rectangle = Rectangle.Intersect(workingArea, formBounds)
|
||||||
|
Dim visiblePercentage As Double = (visibleArea.Width * visibleArea.Height) / (formBounds.Width * formBounds.Height)
|
||||||
|
|
||||||
|
If visiblePercentage < 0.2 Then ' Weniger als 20% sichtbar
|
||||||
|
CenterFormOnScreen()
|
||||||
|
End If
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
LOGGER.Error(ex)
|
||||||
|
' Bei Fehler sicherheitshalber zentrieren
|
||||||
|
CenterFormOnScreen()
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub CenterFormOnScreen()
|
||||||
|
Try
|
||||||
|
' Formular auf dem primären Bildschirm zentrieren
|
||||||
|
Me.StartPosition = FormStartPosition.CenterScreen
|
||||||
|
|
||||||
|
' Alternative: Auf aktuellem Bildschirm zentrieren
|
||||||
|
Dim currentScreen As Screen = Screen.PrimaryScreen
|
||||||
|
Dim x As Integer = currentScreen.WorkingArea.Left + (currentScreen.WorkingArea.Width - Me.Width) \ 2
|
||||||
|
Dim y As Integer = currentScreen.WorkingArea.Top + (currentScreen.WorkingArea.Height - Me.Height) \ 2
|
||||||
|
Me.Location = New Point(x, y)
|
||||||
|
|
||||||
|
LOGGER.Info("Formular wurde zentriert, da es außerhalb des sichtbaren Bereichs lag")
|
||||||
|
Catch ex As Exception
|
||||||
|
LOGGER.Error(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
Private Sub frmValidatorSearch_Shown(sender As Object, e As EventArgs) Handles Me.Shown
|
Private Sub frmValidatorSearch_Shown(sender As Object, e As EventArgs) Handles Me.Shown
|
||||||
|
' Prüfen ob das Formular im sichtbaren Bereich liegt
|
||||||
|
EnsureFormIsVisible()
|
||||||
formLoaded = True
|
formLoaded = True
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user