Compare commits
3 Commits
9dc65ab92f
...
1112fa215c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1112fa215c | ||
|
|
f0259e3f78 | ||
|
|
d9785baf5b |
@@ -1,6 +1,7 @@
|
|||||||
using DbFirst.BlazorWebApp.Models.Grid;
|
using DbFirst.BlazorWebApp.Models.Grid;
|
||||||
using DbFirst.BlazorWebApp.Services;
|
using DbFirst.BlazorWebApp.Services;
|
||||||
using DevExpress.Blazor;
|
using DevExpress.Blazor;
|
||||||
|
using DevExpress.Data.Filtering;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
using Microsoft.AspNetCore.Components.Rendering;
|
using Microsoft.AspNetCore.Components.Rendering;
|
||||||
@@ -24,6 +25,16 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
|||||||
protected bool gridLayoutApplied;
|
protected bool gridLayoutApplied;
|
||||||
protected IGrid? gridRef;
|
protected IGrid? gridRef;
|
||||||
|
|
||||||
|
// --- Datumsfilter-Zustand ---
|
||||||
|
private readonly Dictionary<string, DateTime?> _filterFrom = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly Dictionary<string, DateTime?> _filterTo = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// Stabile Referenzen: werden einmal pro FieldName erstellt und wiederverwendet
|
||||||
|
private readonly Dictionary<string, EventCallback<DateTime?>> _fromCallbacks = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly Dictionary<string, EventCallback<DateTime?>> _toCallbacks = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly Dictionary<string, RenderFragment<GridDataColumnFilterMenuTemplateContext>> _dateFilterTemplates = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly Dictionary<string, GridDataColumnFilterMenuTemplateContext> _filterContexts = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// --- SizeMode ---
|
// --- SizeMode ---
|
||||||
protected SizeMode _sizeMode = SizeMode.Medium;
|
protected SizeMode _sizeMode = SizeMode.Medium;
|
||||||
protected static readonly List<SizeMode> _sizeModes = Enum.GetValues<SizeMode>().ToList();
|
protected static readonly List<SizeMode> _sizeModes = Enum.GetValues<SizeMode>().ToList();
|
||||||
@@ -224,9 +235,134 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
|||||||
builder.AddAttribute(seq++, "DisplayFormat", column.DisplayFormat);
|
builder.AddAttribute(seq++, "DisplayFormat", column.DisplayFormat);
|
||||||
if (column.ReadOnly)
|
if (column.ReadOnly)
|
||||||
builder.AddAttribute(seq++, "ReadOnly", true);
|
builder.AddAttribute(seq++, "ReadOnly", true);
|
||||||
|
if (column.FilterType == ColumnFilterType.Date)
|
||||||
|
builder.AddAttribute(seq++, "FilterMenuTemplate", GetOrCreateDateFilterTemplate(column.FieldName));
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RenderFragment<GridDataColumnFilterMenuTemplateContext> GetOrCreateDateFilterTemplate(string fieldName)
|
||||||
|
{
|
||||||
|
if (!_dateFilterTemplates.TryGetValue(fieldName, out var template))
|
||||||
|
{
|
||||||
|
// EventCallbacks einmalig erstellen – stabile Referenzen über alle Renders
|
||||||
|
_fromCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, (DateTime? v) => OnFilterFromChanged(fieldName, v));
|
||||||
|
_toCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, (DateTime? v) => OnFilterToChanged(fieldName, v));
|
||||||
|
template = BuildDateFilterTemplate(fieldName);
|
||||||
|
_dateFilterTemplates[fieldName] = template;
|
||||||
|
}
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RenderFragment<GridDataColumnFilterMenuTemplateContext> BuildDateFilterTemplate(string fieldName) =>
|
||||||
|
ctx => b =>
|
||||||
|
{
|
||||||
|
_filterContexts[fieldName] = ctx;
|
||||||
|
SyncDateFilterFromContext(fieldName, ctx.FilterCriteria);
|
||||||
|
int s = 0;
|
||||||
|
b.OpenElement(s++, "div");
|
||||||
|
b.AddAttribute(s++, "class", "date-filter-menu p-2");
|
||||||
|
|
||||||
|
// Ab Datum
|
||||||
|
b.OpenElement(s++, "div");
|
||||||
|
b.AddAttribute(s++, "class", "mb-2");
|
||||||
|
b.OpenElement(s++, "label");
|
||||||
|
b.AddAttribute(s++, "class", "form-label small fw-semibold");
|
||||||
|
b.AddContent(s++, "Ab Datum");
|
||||||
|
b.CloseElement();
|
||||||
|
b.OpenComponent<DxDateEdit<DateTime?>>(s++);
|
||||||
|
b.AddAttribute(s++, "Date", _filterFrom.GetValueOrDefault(fieldName));
|
||||||
|
b.AddAttribute(s++, "DateChanged", _fromCallbacks[fieldName]);
|
||||||
|
b.AddAttribute(s++, "ClearButtonDisplayMode", DataEditorClearButtonDisplayMode.Auto);
|
||||||
|
b.AddAttribute(s++, "NullText", "Kein Startdatum");
|
||||||
|
b.AddAttribute(s++, "Width", "100%");
|
||||||
|
b.CloseComponent();
|
||||||
|
b.CloseElement();
|
||||||
|
|
||||||
|
// Bis Datum
|
||||||
|
b.OpenElement(s++, "div");
|
||||||
|
b.AddAttribute(s++, "class", "mb-0");
|
||||||
|
b.OpenElement(s++, "label");
|
||||||
|
b.AddAttribute(s++, "class", "form-label small fw-semibold");
|
||||||
|
b.AddContent(s++, "Bis Datum");
|
||||||
|
b.CloseElement();
|
||||||
|
b.OpenComponent<DxDateEdit<DateTime?>>(s++);
|
||||||
|
b.AddAttribute(s++, "Date", _filterTo.GetValueOrDefault(fieldName));
|
||||||
|
b.AddAttribute(s++, "DateChanged", _toCallbacks[fieldName]);
|
||||||
|
b.AddAttribute(s++, "ClearButtonDisplayMode", DataEditorClearButtonDisplayMode.Auto);
|
||||||
|
b.AddAttribute(s++, "NullText", "Kein Enddatum");
|
||||||
|
b.AddAttribute(s++, "Width", "100%");
|
||||||
|
b.CloseComponent();
|
||||||
|
b.CloseElement();
|
||||||
|
|
||||||
|
b.CloseElement();
|
||||||
|
};
|
||||||
|
|
||||||
|
private void SyncDateFilterFromContext(string fieldName, CriteriaOperator? criteria)
|
||||||
|
{
|
||||||
|
if (criteria == null)
|
||||||
|
{
|
||||||
|
_filterFrom[fieldName] = null;
|
||||||
|
_filterTo[fieldName] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime? from = null;
|
||||||
|
DateTime? to = null;
|
||||||
|
|
||||||
|
if (criteria is GroupOperator group)
|
||||||
|
{
|
||||||
|
foreach (var op in group.Operands.OfType<BinaryOperator>())
|
||||||
|
ParseDateOperand(op, ref from, ref to);
|
||||||
|
}
|
||||||
|
else if (criteria is BinaryOperator binary)
|
||||||
|
{
|
||||||
|
ParseDateOperand(binary, ref from, ref to);
|
||||||
|
}
|
||||||
|
|
||||||
|
_filterFrom[fieldName] = from;
|
||||||
|
_filterTo[fieldName] = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ParseDateOperand(BinaryOperator op, ref DateTime? from, ref DateTime? to)
|
||||||
|
{
|
||||||
|
if (op.RightOperand is not OperandValue val || val.Value is not DateTime dt) return;
|
||||||
|
if (op.OperatorType == BinaryOperatorType.GreaterOrEqual) from = dt;
|
||||||
|
else if (op.OperatorType == BinaryOperatorType.Less) to = dt.AddDays(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFilterFromChanged(string fieldName, DateTime? value)
|
||||||
|
{
|
||||||
|
_filterFrom[fieldName] = value;
|
||||||
|
ApplyDateFilter(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFilterToChanged(string fieldName, DateTime? value)
|
||||||
|
{
|
||||||
|
_filterTo[fieldName] = value;
|
||||||
|
ApplyDateFilter(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyDateFilter(string fieldName)
|
||||||
|
{
|
||||||
|
var ops = new List<CriteriaOperator>();
|
||||||
|
if (_filterFrom.TryGetValue(fieldName, out var from) && from.HasValue)
|
||||||
|
ops.Add(new BinaryOperator(fieldName, from.Value.Date, BinaryOperatorType.GreaterOrEqual));
|
||||||
|
if (_filterTo.TryGetValue(fieldName, out var to) && to.HasValue)
|
||||||
|
ops.Add(new BinaryOperator(fieldName, to.Value.Date.AddDays(1), BinaryOperatorType.Less));
|
||||||
|
|
||||||
|
CriteriaOperator? criteria = ops.Count switch
|
||||||
|
{
|
||||||
|
0 => null,
|
||||||
|
1 => ops[0],
|
||||||
|
_ => new GroupOperator(GroupOperatorType.And, ops)
|
||||||
|
};
|
||||||
|
|
||||||
|
gridRef?.SetFieldFilterCriteria(fieldName, criteria);
|
||||||
|
if (_filterContexts.TryGetValue(fieldName, out var ctx))
|
||||||
|
ctx.FilterCriteria = criteria;
|
||||||
|
_ = InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
protected void SetEditContext(EditContext context)
|
protected void SetEditContext(EditContext context)
|
||||||
{
|
{
|
||||||
if (editContext == context) return;
|
if (editContext == context) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user