using DbFirst.BlazorWebApp.Models.Grid; using DbFirst.BlazorWebApp.Services; using DevExpress.Blazor; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; namespace DbFirst.BlazorWebApp.Components; public abstract class BandGridBase : ComponentBase { [Inject] protected BandLayoutService BandLayoutService { get; set; } = default!; // --- Abstract: jedes Grid definiert diese selbst --- protected abstract string LayoutKey { get; } protected abstract List ColumnDefinitions { get; } // --- Band-Layout Felder --- protected BandLayout bandLayout = new(); protected Dictionary columnBandAssignments = new(); protected List bandOptions = new(); protected Dictionary columnLookup = new(); protected string? layoutUser; protected bool gridLayoutApplied; protected IGrid? gridRef; // --- SizeMode --- protected SizeMode _sizeMode = SizeMode.Medium; protected static readonly List _sizeModes = Enum.GetValues().ToList(); private const string LayoutType = "GRID_BANDS"; // --- Lifecycle --- protected async Task InitializeBandLayoutAsync() { columnLookup = ColumnDefinitions.ToDictionary(c => c.FieldName, StringComparer.OrdinalIgnoreCase); layoutUser = await BandLayoutService.EnsureLayoutUserAsync(); bandLayout = await BandLayoutService.LoadBandLayoutAsync(LayoutType, LayoutKey, layoutUser, columnLookup); columnBandAssignments = BandLayoutService.BuildAssignmentsFromLayout(bandLayout); ApplyColumnLayoutFromStorage(); _sizeMode = bandLayout.SizeMode; UpdateBandOptions(); } protected async Task ApplyGridLayoutAfterRenderAsync() { if (!gridLayoutApplied && gridRef != null && bandLayout.GridLayout != null) { gridRef.LoadLayout(bandLayout.GridLayout); gridLayoutApplied = true; await InvokeAsync(StateHasChanged); } } // --- Layout speichern / zurücksetzen --- protected async Task SaveLayoutAsync() { if (string.IsNullOrWhiteSpace(layoutUser)) return; CaptureColumnLayoutFromGrid(); await BandLayoutService.SaveBandLayoutAsync(LayoutType, LayoutKey, layoutUser, bandLayout); } protected async Task ResetLayoutAsync() { if (string.IsNullOrWhiteSpace(layoutUser)) return; await BandLayoutService.ResetBandLayoutAsync(LayoutType, LayoutKey, layoutUser); bandLayout = new BandLayout(); columnBandAssignments.Clear(); UpdateBandOptions(); foreach (var column in ColumnDefinitions) column.Width = null; columnLookup = ColumnDefinitions.ToDictionary(c => c.FieldName, StringComparer.OrdinalIgnoreCase); _sizeMode = SizeMode.Medium; gridRef?.LoadLayout(new GridPersistentLayout()); gridLayoutApplied = false; } private void CaptureColumnLayoutFromGrid() { if (gridRef == null) return; var layout = gridRef.SaveLayout(); bandLayout.GridLayout = layout; bandLayout.SizeMode = _sizeMode; var orderedColumns = layout.Columns .Where(c => !string.IsNullOrWhiteSpace(c.FieldName)) .OrderBy(c => c.VisibleIndex) .ToList(); bandLayout.ColumnOrder = orderedColumns.Select(c => c.FieldName).ToList(); bandLayout.ColumnWidths = orderedColumns .Where(c => !string.IsNullOrWhiteSpace(c.Width)) .ToDictionary(c => c.FieldName, c => c.Width, StringComparer.OrdinalIgnoreCase); } private void ApplyColumnLayoutFromStorage() { foreach (var column in ColumnDefinitions) { if (bandLayout.ColumnWidths.TryGetValue(column.FieldName, out var width) && !string.IsNullOrWhiteSpace(width)) column.Width = width; } columnLookup = ColumnDefinitions.ToDictionary(c => c.FieldName, StringComparer.OrdinalIgnoreCase); } // --- Band-Methoden --- protected bool CanSaveBandLayout => !string.IsNullOrWhiteSpace(layoutUser); protected virtual bool ShowCommandColumn => true; protected void AddBand() { bandLayout.Bands.Add(new BandDefinition { Id = Guid.NewGuid().ToString("N"), Caption = "Band" }); UpdateBandOptions(); } protected void RemoveBand(BandDefinition band) { bandLayout.Bands.Remove(band); foreach (var key in columnBandAssignments.Where(p => p.Value == band.Id).Select(p => p.Key).ToList()) columnBandAssignments.Remove(key); UpdateBandOptions(); SyncBandsFromAssignments(); } protected void UpdateBandCaption(BandDefinition band, string value) { band.Caption = value; UpdateBandOptions(); } protected void UpdateColumnBand(string fieldName, string? bandId) { if (string.IsNullOrWhiteSpace(bandId)) columnBandAssignments.Remove(fieldName); else columnBandAssignments[fieldName] = bandId; SyncBandsFromAssignments(); } protected string GetColumnBand(string fieldName) => columnBandAssignments.TryGetValue(fieldName, out var bandId) ? bandId : string.Empty; protected void SyncBandsFromAssignments() { foreach (var band in bandLayout.Bands) { band.Columns = ColumnDefinitions .Where(c => columnBandAssignments.TryGetValue(c.FieldName, out var id) && id == band.Id) .Select(c => c.FieldName) .ToList(); } StateHasChanged(); } protected void UpdateBandOptions() { bandOptions = new List { new() { Id = string.Empty, Caption = "Ohne Band" } }; bandOptions.AddRange(bandLayout.Bands.Select(b => new BandOption { Id = b.Id, Caption = b.Caption })); } // --- SizeMode --- protected string FormatSizeText(SizeMode size) => size switch { SizeMode.Small => "Klein", SizeMode.Medium => "Mittel", SizeMode.Large => "Groß", _ => size.ToString() }; protected void OnSizeChange(DropDownButtonItemClickEventArgs args) { _sizeMode = Enum.Parse(args.ItemInfo.Id); } // --- RenderColumns / BuildDataColumn --- protected RenderFragment RenderColumns() => builder => { var seq = 0; if (ShowCommandColumn) { builder.OpenComponent(seq++); builder.AddAttribute(seq++, "Width", "120px"); builder.CloseComponent(); } var grouped = bandLayout.Bands.SelectMany(b => b.Columns).ToHashSet(StringComparer.OrdinalIgnoreCase); foreach (var column in ColumnDefinitions.Where(c => !grouped.Contains(c.FieldName))) BuildDataColumn(builder, ref seq, column); foreach (var band in bandLayout.Bands) { if (band.Columns.Count == 0) continue; builder.OpenComponent(seq++); builder.AddAttribute(seq++, "Caption", band.Caption); builder.AddAttribute(seq++, "Columns", (RenderFragment)(bandBuilder => { var bandSeq = 0; foreach (var columnName in band.Columns) { if (columnLookup.TryGetValue(columnName, out var column)) BuildDataColumn(bandBuilder, ref bandSeq, column); } })); builder.CloseComponent(); } }; protected void BuildDataColumn(RenderTreeBuilder builder, ref int seq, ColumnDefinition column) { builder.OpenComponent(seq++); builder.AddAttribute(seq++, "FieldName", column.FieldName); builder.AddAttribute(seq++, "Caption", column.Caption); if (!string.IsNullOrWhiteSpace(column.Width)) builder.AddAttribute(seq++, "Width", column.Width); if (!string.IsNullOrWhiteSpace(column.DisplayFormat)) builder.AddAttribute(seq++, "DisplayFormat", column.DisplayFormat); if (column.ReadOnly) builder.AddAttribute(seq++, "ReadOnly", true); builder.CloseComponent(); } }