Introduce Add, Edit, and Delete buttons with Bootstrap Icons in the toolbars of CatalogsGrid and MassDataGrid. Hide the default command column by overriding ShowCommandColumn. Update BandGridBase to conditionally render the command column. Track focused row index for toolbar actions, enabling row operations via toolbar instead of the grid's built-in command column. Add Bootstrap Icons stylesheet to App.razor.
219 lines
8.1 KiB
C#
219 lines
8.1 KiB
C#
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<TItem> : ComponentBase
|
|
{
|
|
[Inject] protected BandLayoutService BandLayoutService { get; set; } = default!;
|
|
|
|
// --- Abstract: jedes Grid definiert diese selbst ---
|
|
protected abstract string LayoutKey { get; }
|
|
protected abstract List<ColumnDefinition> ColumnDefinitions { get; }
|
|
|
|
// --- Band-Layout Felder ---
|
|
protected BandLayout bandLayout = new();
|
|
protected Dictionary<string, string> columnBandAssignments = new();
|
|
protected List<BandOption> bandOptions = new();
|
|
protected Dictionary<string, ColumnDefinition> columnLookup = new();
|
|
protected string? layoutUser;
|
|
protected bool gridLayoutApplied;
|
|
protected IGrid? gridRef;
|
|
|
|
// --- SizeMode ---
|
|
protected SizeMode _sizeMode = SizeMode.Medium;
|
|
protected static readonly List<SizeMode> _sizeModes = Enum.GetValues<SizeMode>().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<BandOption> { 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<SizeMode>(args.ItemInfo.Id);
|
|
}
|
|
|
|
// --- RenderColumns / BuildDataColumn ---
|
|
protected RenderFragment RenderColumns() => builder =>
|
|
{
|
|
var seq = 0;
|
|
if (ShowCommandColumn)
|
|
{
|
|
builder.OpenComponent<DxGridCommandColumn>(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<DxGridBandColumn>(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<DxGridDataColumn>(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();
|
|
}
|
|
} |