From 935b6abf9a76796f63201c39d088b5b392f52e16 Mon Sep 17 00:00:00 2001 From: Loretta Date: Fri, 7 Nov 2025 14:10:49 +0100 Subject: [PATCH] MgGridBase improvements, fixes --- .../Components/Grids/MgGridBase.cs | 753 +++++++++--------- 1 file changed, 376 insertions(+), 377 deletions(-) diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs b/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs index a75d8eb..dfd5ebf 100644 --- a/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs +++ b/AyCode.Blazor.Components/Components/Grids/MgGridBase.cs @@ -1,378 +1,377 @@ -//using AyCode.Core; -//using AyCode.Core.Enums; -//using AyCode.Core.Extensions; -//using AyCode.Core.Helpers; -//using AyCode.Core.Interfaces; -//using AyCode.Core.Loggers; -//using AyCode.Services.Server.SignalRs; -//using AyCode.Services.SignalRs; -//using AyCode.Utils.Extensions; -//using DevExpress.Blazor; -//using DevExpress.Blazor.Internal; -//using Microsoft.AspNetCore.Components; -//using System.ComponentModel; - -//namespace AyCode.Blazor.Components.Components.Grids; - -//public interface IMgGridBase -//{ - -//} - -//public abstract class MgGridBaseGuid : MgGridBase -// where TSignalRDataSource : AcSignalRDataSource where TDataItem : class, IId where TLoggerClient : AcLoggerBase -//{ -//} - -//public abstract class MgGridBaseInt : MgGridBase -// where TSignalRDataSource : AcSignalRDataSource where TDataItem : class, IId where TLoggerClient : AcLoggerBase -//{ -//} - -//public abstract class MgGridBase : DxGrid, IMgGridBase -// where TSignalRDataSource : AcSignalRDataSource where TDataItem : class where TLoggerClient : AcLoggerBase -//{ -// protected bool IsFirstInitializeParameters; -// private TSignalRDataSource _dataSource = null!; -// private IList _dataSourceParam = []; -// private string _gridLogName; - -// public MgGridBase() : base() -// { -// } - -// [Parameter] public TLoggerClient Logger { get; set; } -// [Parameter] public string GridName { get; set; } -// [Parameter] public object[]? ContextIds { get; set; } - -// private string? _filterText = null; - -// [Parameter] -// public string? FilterText -// { -// get => _filterText; -// set -// { -// _filterText = value; - -// if (_dataSource != null! && _dataSource.FilterText != value) -// { -// _dataSource.FilterText = value; -// ReloadDataSourceAsync().Forget(); -// } -// } -// } - -// [Parameter] public AcSignalRClientBase SignalRClient { get; set; } - -// [Parameter] public int GetAllMessageTag { get; set; } -// [Parameter] public int GetItemMessageTag { get; set; } -// [Parameter] public int AddMessageTag { get; set; } -// [Parameter] public int UpdateMessageTag { get; set; } -// [Parameter] public int RemoveMessageTag { get; set; } - -// protected new EventCallback DataItemDeleting { get; set; } -// [Parameter] public EventCallback OnGridItemDeleting { get; set; } - -// protected new EventCallback EditModelSaving { get; set; } -// [Parameter] public EventCallback OnGridEditModelSaving { get; set; } - -// [Parameter] public EventCallback> OnDataSourceChanged { get; set; } -// [Parameter] public EventCallback> OnGridItemChanging { get; set; } - -// /// -// /// After the server has responded! -// /// -// [Parameter] -// public EventCallback> OnGridItemChanged { get; set; } - -// [Parameter] -// [DefaultValue(null)] -// [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "BL0007:Component parameters should be auto properties", Justification = "")] -// public IList DataSource -// { -// get -// { -// if (_dataSource == null && Data != null) -// { -// Logger.Error($"{_gridLogName} Use the DataSource parameter instead of Data!"); -// throw new NullReferenceException($"{_gridLogName} Use the DataSource parameter instead of Data!"); -// } - -// return _dataSource!; -// } -// set -// { -// _dataSourceParam = value; - -// if (_dataSource != null! && _dataSourceParam is List workingReferenceList) -// _dataSource.SetWorkingReferenceList(workingReferenceList); -// } -// } - -// protected override async Task OnInitializedAsync() -// { -// if (Logger == null) -// throw new NullReferenceException($"[{GetType().Name}] Logger == null"); - -// if (SignalRClient == null) -// { -// Logger.Error($"[{GetType().Name}] SignalRClient == null"); -// throw new NullReferenceException($"[{GetType().Name}] SignalRClient == null"); -// } - -// var crudTags = new SignalRCrudTags(GetAllMessageTag, GetItemMessageTag, AddMessageTag, UpdateMessageTag, RemoveMessageTag); - -// _dataSource =(TSignalRDataSource)Activator.CreateInstance(typeof(TSignalRDataSource), SignalRClient, crudTags, ContextIds)!; -// _dataSource.FilterText = FilterText; -// //_dataSource = new SignalRDataSource(SignalRClient, crudTags, ContextIds) { FilterText = FilterText }; - -// Data = _dataSource; - -// _dataSource.OnDataSourceLoaded += OnDataSourceLoaded; -// _dataSource.OnDataSourceItemChanged += OnDataSourceItemChanged; - -// await base.OnInitializedAsync(); -// } - -// private async Task OnDataSourceItemChanged(ItemChangedEventArgs args) -// { -// if (args.TrackingState is TrackingState.GetAll or TrackingState.None) return; - -// Logger.Debug($"{_gridLogName} OnDataSourceItemChanged; trackingState: {args.TrackingState}"); - -// var changedEventArgs = new GridDataItemChangedEventArgs(this, args.Item, args.TrackingState); -// await OnGridItemChanged.InvokeAsync(changedEventArgs); - -// if (!changedEventArgs.CancelStateChangeInvoke) -// { -// //BeginUpdate(); -// await InvokeAsync(StateHasChanged); //TODO: bezárja a DetailRow-t! pl: az email-nél IsReaded=true update... - J. -// //EndUpdate(); -// } -// } - -// private Task OnDataSourceLoaded() -// { -// Logger.Debug($"{_gridLogName} OnDataSourceLoaded; Count: {_dataSource.Count}"); - -// Reload(); -// //_dataSource.LoadItem(_dataSource.First().Id).Forget(); -// return OnDataSourceChanged.InvokeAsync(_dataSource); -// } - -// protected override async Task OnAfterRenderAsync(bool firstRender) -// { -// if (firstRender) -// { -// if (_dataSourceParam != null!) await _dataSource.LoadDataSource(_dataSourceParam, true, true); -// else _dataSource.LoadDataSourceAsync(true).Forget(); -// } - -// await base.OnAfterRenderAsync(firstRender); -// } - -// public Task AddDataItem(TDataItem dataItem) -// { -// if (dataItem.Id.IsNullOrEmpty()) dataItem.Id = Guid.NewGuid(); -// return _dataSource.Add(dataItem, true); -// } - -// public Task AddDataItemAsync(TDataItem dataItem) -// { -// if (dataItem.Id.IsNullOrEmpty()) dataItem.Id = Guid.NewGuid(); -// _dataSource.Add(dataItem); - -// return SaveChangesToServerAsync(); -// } - -// private async Task OnItemSaving(GridEditModelSavingEventArgs e) -// { -// var dataItem = (e.EditModel as TDataItem)!; - -// if (e.IsNew && dataItem.Id.IsNullOrEmpty()) dataItem.Id = Guid.NewGuid(); - -// var logText = e.IsNew ? "add" : "update"; -// Logger.Debug($"{_gridLogName} OnItemSaving {logText}; Id: {dataItem.Id}"); - -// await OnGridEditModelSaving.InvokeAsync(e); - -// if (e.Cancel) -// { -// Logger.Debug($"{_gridLogName} OnItemSaving {logText} canceled; Id: {dataItem.Id}"); -// return; -// } - -// if (e.IsNew) await AddDataItemAsync(dataItem); -// else await UpdateDataItemAsync(dataItem); - -// _dataSource.UpdateCollection(dataItem, false); -// } - -// private Task SaveChangesToServerAsync() -// { -// try -// { -// return _dataSource.SaveChangesAsync(); -// } -// catch (Exception ex) -// { -// Logger.Error($"{_gridLogName} SaveChangesToServerAsync->SaveChangesAsync error!", ex); -// } - -// return Task.CompletedTask; -// } - -// private async Task SaveChangesToServer() -// { -// var result = false; - -// try -// { -// var unsavedItems = await _dataSource.SaveChanges(); - -// if ((result = unsavedItems.Count == 0) == false) -// Logger.Error($"{_gridLogName} SaveChangesToServer->SaveChanges error! unsavedCount: {unsavedItems.Count}"); -// } -// catch (Exception ex) -// { -// Logger.Error($"{_gridLogName} OnItemSaving", ex); -// } - -// return result; -// } - -// private async Task OnItemDeleting(GridDataItemDeletingEventArgs e) -// { -// Logger.Debug($"{_gridLogName} OnItemDeleting"); - -// await OnGridItemDeleting.InvokeAsync(e); - -// if (e.Cancel) -// { -// Logger.Debug($"{_gridLogName} OnItemDeleting canceled"); -// return; -// } - -// var dataItem = (e.DataItem as TDataItem)!; -// await RemoveDataItem(dataItem); -// } - -// private void OnCustomizeElement(GridCustomizeElementEventArgs e) -// { -// if (e.ElementType == GridElementType.DetailCell) -// { -// e.Style = "padding: 0.5rem; opacity: 0.75"; -// } -// else if (false && e.ElementType == GridElementType.DataCell && e.Column.Name == nameof(IId.Id)) -// { -// e.Column.Visible = AcDomain.IsDeveloperVersion; -// e.Column.ShowInColumnChooser = AcDomain.IsDeveloperVersion; -// } -// } - -// protected override Task SetParametersAsyncCore(ParameterView parameters) -// { -// if (!IsFirstInitializeParameters) -// { -// //if (typeof(TDataItem) is IId || typeof(TDataItem) is IId) -// KeyFieldName = "Id"; - -// base.DataItemDeleting = EventCallback.Factory.Create(this, OnItemDeleting); -// base.EditModelSaving = EventCallback.Factory.Create(this, OnItemSaving); - -// CustomizeElement += OnCustomizeElement; - -// //ShowFilterRow = true; -// //PageSize = 4; -// //ShowGroupPanel = true; -// //AllowSort = false; - -// TextWrapEnabled = false; -// AllowSelectRowByClick = true; -// HighlightRowOnHover = true; -// AutoCollapseDetailRow = true; -// AutoExpandAllGroupRows = false; -// //KeyboardNavigationEnabled = true; - -// //var dataColumns = GetDataColumns(); - -// //var idColumn = dataColumns.FirstOrDefault(x => x.FieldName == nameof(IId.Id)); -// //if (idColumn != null) -// //{ -// // idColumn.ShowInColumnChooser = AcDomain.IsDeveloperVersion; -// // idColumn.Visible = !AcDomain.IsDeveloperVersion; -// //} - -// IsFirstInitializeParameters = true; -// } - -// return base.SetParametersAsyncCore(parameters); -// } - - -// protected override void OnParametersSet() -// { -// base.OnParametersSet(); - -// if (GridName.IsNullOrWhiteSpace()) GridName = $"{typeof(TDataItem).Name}Grid"; - -// _gridLogName = $"[{GridName}]"; - -// } - -// //public Task AddDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Add); - -// public Task UpdateDataItem(TDataItem dataItem) => _dataSource.Update(dataItem, true); - -// public Task UpdateDataItemAsync(TDataItem dataItem) -// { -// _dataSource.Update(dataItem, false); -// return SaveChangesToServerAsync(); -// } -// //public Task UpdateDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Update); - -// public Task AddOrUpdateDataItem(TDataItem dataItem) => _dataSource.AddOrUpdate(dataItem, true); - -// public Task RemoveDataItem(TDataItem dataItem) => _dataSource.Remove(dataItem, true); -// //public Task RemoveDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Remove); - -// public Task RemoveDataItem(Guid id) => RemoveDataItem(id, RemoveMessageTag); - -// public Task RemoveDataItem(Guid id, int messageTag) -// { -// var dataItem = _dataSource.FirstOrDefault(x => x.Id == id); -// if (dataItem == null) return Task.CompletedTask; - -// return _dataSource.Remove(dataItem, true); -// } - -// public Task ReloadDataSourceAsync() -// { -// return _dataSource.LoadDataSourceAsync(false); -// } -//} - -//public class GridDataItemChangingEventArgs : GridDataItemChangedEventArgs where TDataItem : class -//{ -// internal GridDataItemChangingEventArgs(IMgGridBase grid, TDataItem dataItem, TrackingState trackingState) : base(grid, dataItem, trackingState) -// { -// } - -// public bool IsCanceled { get; set; } -//} - -//public class GridDataItemChangedEventArgs where TDataItem : class -//{ -// internal GridDataItemChangedEventArgs(IMgGridBase grid, TDataItem dataItem, TrackingState trackingState) -// { -// Grid = grid ?? throw new ArgumentNullException(nameof(grid)); -// DataItem = dataItem; -// TrackingState = trackingState; -// } +using AyCode.Core; +using AyCode.Core.Enums; +using AyCode.Core.Helpers; +using AyCode.Core.Interfaces; +using AyCode.Core.Loggers; +using AyCode.Services.Server.SignalRs; +using AyCode.Services.SignalRs; +using AyCode.Utils.Extensions; +using DevExpress.Blazor; +using Microsoft.AspNetCore.Components; +using System.ComponentModel; + +namespace AyCode.Blazor.Components.Components.Grids; + +public interface IMgGridBase +{ + +} + +public abstract class MgGridBase : DxGrid, IMgGridBase + where TSignalRDataSource : AcSignalRDataSource> + where TDataItem : class, IId where TId : struct + where TLoggerClient : AcLoggerBase +{ + private readonly EqualityComparer _equalityComparer = EqualityComparer.Default; + + protected bool IsFirstInitializeParameters; + private TSignalRDataSource _dataSource = null!; + private IList _dataSourceParam = []; + private string _gridLogName; + + public MgGridBase() : base() + { + } + + protected bool HasIdValue(TDataItem dataItem) => _equalityComparer.Equals(dataItem.Id, default);//dataItem.Id.IsNullOrEmpty(); + protected bool IdEquals(TId id1, TId id2) => _equalityComparer.Equals(id1, id2); + + [Parameter] public TLoggerClient Logger { get; set; } + [Parameter] public string GridName { get; set; } + [Parameter] public object[]? ContextIds { get; set; } + + private string? _filterText = null; + + [Parameter] + public string? FilterText + { + get => _filterText; + set + { + _filterText = value; + + if (_dataSource != null! && _dataSource.FilterText != value) + { + _dataSource.FilterText = value; + ReloadDataSourceAsync().Forget(); + } + } + } + + [Parameter] public AcSignalRClientBase SignalRClient { get; set; } + + [Parameter] public int GetAllMessageTag { get; set; } + [Parameter] public int GetItemMessageTag { get; set; } + [Parameter] public int AddMessageTag { get; set; } + [Parameter] public int UpdateMessageTag { get; set; } + [Parameter] public int RemoveMessageTag { get; set; } + + protected new EventCallback DataItemDeleting { get; set; } + [Parameter] public EventCallback OnGridItemDeleting { get; set; } + + protected new EventCallback EditModelSaving { get; set; } + [Parameter] public EventCallback OnGridEditModelSaving { get; set; } + + [Parameter] public EventCallback> OnDataSourceChanged { get; set; } + [Parameter] public EventCallback> OnGridItemChanging { get; set; } + + /// + /// After the server has responded! + /// + [Parameter] + public EventCallback> OnGridItemChanged { get; set; } + + [Parameter] + [DefaultValue(null)] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "BL0007:Component parameters should be auto properties", Justification = "")] + public IList DataSource + { + get + { + if (_dataSource == null && Data != null) + { + Logger.Error($"{_gridLogName} Use the DataSource parameter instead of Data!"); + throw new NullReferenceException($"{_gridLogName} Use the DataSource parameter instead of Data!"); + } + + return _dataSource!; + } + set + { + _dataSourceParam = value; + + if (_dataSource != null!)// && _dataSourceParam is List workingReferenceList) + _dataSource.SetWorkingReferenceList(_dataSourceParam); + } + } + + protected override async Task OnInitializedAsync() + { + if (Logger == null) + throw new NullReferenceException($"[{GetType().Name}] Logger == null"); + + if (SignalRClient == null) + { + Logger.Error($"[{GetType().Name}] SignalRClient == null"); + throw new NullReferenceException($"[{GetType().Name}] SignalRClient == null"); + } + + var crudTags = new SignalRCrudTags(GetAllMessageTag, GetItemMessageTag, AddMessageTag, UpdateMessageTag, RemoveMessageTag); + + _dataSource = (TSignalRDataSource)Activator.CreateInstance(typeof(TSignalRDataSource), SignalRClient, crudTags, ContextIds)!; + _dataSource.FilterText = FilterText; + //_dataSource = new SignalRDataSource(SignalRClient, crudTags, ContextIds) { FilterText = FilterText }; + + Data = _dataSource; + + _dataSource.OnDataSourceLoaded += OnDataSourceLoaded; + _dataSource.OnDataSourceItemChanged += OnDataSourceItemChanged; + + await base.OnInitializedAsync(); + } + + private async Task OnDataSourceItemChanged(ItemChangedEventArgs args) + { + if (args.TrackingState is TrackingState.GetAll or TrackingState.None) return; + + Logger.Debug($"{_gridLogName} OnDataSourceItemChanged; trackingState: {args.TrackingState}"); + + var changedEventArgs = new GridDataItemChangedEventArgs(this, args.Item, args.TrackingState); + await OnGridItemChanged.InvokeAsync(changedEventArgs); + + if (!changedEventArgs.CancelStateChangeInvoke) + { + //BeginUpdate(); + await InvokeAsync(StateHasChanged); //TODO: bezárja a DetailRow-t! pl: az email-nél IsReaded=true update... - J. + //EndUpdate(); + } + } + + private Task OnDataSourceLoaded() + { + Logger.Debug($"{_gridLogName} OnDataSourceLoaded; Count: {_dataSource.Count}"); + + Reload(); + //_dataSource.LoadItem(_dataSource.First().Id).Forget(); + return OnDataSourceChanged.InvokeAsync(_dataSource); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + if (_dataSourceParam != null!) await _dataSource.LoadDataSource(_dataSourceParam, true, true); + else _dataSource.LoadDataSourceAsync(true).Forget(); + } + + await base.OnAfterRenderAsync(firstRender); + } + + public Task AddDataItem(TDataItem dataItem) + { + //TODO: !!! - J. + //if (!HasIdValue(dataItem)) dataItem.Id = Guid.NewGuid(); + return _dataSource.Add(dataItem, true); + } + + public Task AddDataItemAsync(TDataItem dataItem) + { + //TODO: !!! - J. + //if (!HasIdValue(dataItem)) dataItem.Id = Guid.NewGuid(); + _dataSource.Add(dataItem); + + return SaveChangesToServerAsync(); + } + + private async Task OnItemSaving(GridEditModelSavingEventArgs e) + { + var dataItem = (e.EditModel as TDataItem)!; + + //TODO: !!! - J. + //if (e.IsNew && !HasIdValue(dataItem)) dataItem.Id = Guid.NewGuid(); + + var logText = e.IsNew ? "add" : "update"; + Logger.Debug($"{_gridLogName} OnItemSaving {logText}; Id: {dataItem.Id}"); + + await OnGridEditModelSaving.InvokeAsync(e); + + if (e.Cancel) + { + Logger.Debug($"{_gridLogName} OnItemSaving {logText} canceled; Id: {dataItem.Id}"); + return; + } + + if (e.IsNew) await AddDataItemAsync(dataItem); + else await UpdateDataItemAsync(dataItem); + + //var equalityComparer = EqualityComparer.Default; + //var index = CollectionExtensions.FindIndex(_dataSource, x => equalityComparer.Equals(x.Id, dataItem.Id)); + //_dataSource.UpdateCollectionByIndex(index, dataItem, false); + + //_dataSource.UpdateCollectionById(dataItem.Id, false); + } + + private Task SaveChangesToServerAsync() + { + try + { + return _dataSource.SaveChangesAsync(); + } + catch (Exception ex) + { + Logger.Error($"{_gridLogName} SaveChangesToServerAsync->SaveChangesAsync error!", ex); + } + + return Task.CompletedTask; + } + + private async Task SaveChangesToServer() + { + var result = false; + + try + { + var unsavedItems = await _dataSource.SaveChanges(); + + if (!(result = unsavedItems.Count == 0)) + Logger.Error($"{_gridLogName} SaveChangesToServer->SaveChanges error! unsavedCount: {unsavedItems.Count}"); + } + catch (Exception ex) + { + Logger.Error($"{_gridLogName} OnItemSaving", ex); + } + + return result; + } + + private async Task OnItemDeleting(GridDataItemDeletingEventArgs e) + { + Logger.Debug($"{_gridLogName} OnItemDeleting"); + + await OnGridItemDeleting.InvokeAsync(e); + + if (e.Cancel) + { + Logger.Debug($"{_gridLogName} OnItemDeleting canceled"); + return; + } + + var dataItem = (e.DataItem as TDataItem)!; + await RemoveDataItem(dataItem); + } + + private void OnCustomizeElement(GridCustomizeElementEventArgs e) + { + if (e.ElementType == GridElementType.DetailCell) + { + e.Style = "padding: 0.5rem; opacity: 0.75"; + } + else if (false && e.ElementType == GridElementType.DataCell && e.Column.Name == nameof(IId.Id)) + { + e.Column.Visible = AcDomain.IsDeveloperVersion; + e.Column.ShowInColumnChooser = AcDomain.IsDeveloperVersion; + } + } + + protected override Task SetParametersAsyncCore(ParameterView parameters) + { + if (!IsFirstInitializeParameters) + { + //if (typeof(TDataItem) is IId || typeof(TDataItem) is IId) + KeyFieldName = "Id"; + + base.DataItemDeleting = EventCallback.Factory.Create(this, OnItemDeleting); + base.EditModelSaving = EventCallback.Factory.Create(this, OnItemSaving); + + CustomizeElement += OnCustomizeElement; + + //ShowFilterRow = true; + //PageSize = 4; + //ShowGroupPanel = true; + //AllowSort = false; + + TextWrapEnabled = false; + AllowSelectRowByClick = true; + HighlightRowOnHover = true; + AutoCollapseDetailRow = true; + AutoExpandAllGroupRows = false; + //KeyboardNavigationEnabled = true; + + //var dataColumns = GetDataColumns(); + + //var idColumn = dataColumns.FirstOrDefault(x => x.FieldName == nameof(IId.Id)); + //if (idColumn != null) + //{ + // idColumn.ShowInColumnChooser = AcDomain.IsDeveloperVersion; + // idColumn.Visible = !AcDomain.IsDeveloperVersion; + //} + + IsFirstInitializeParameters = true; + } + + return base.SetParametersAsyncCore(parameters); + } + + + protected override void OnParametersSet() + { + base.OnParametersSet(); + + if (GridName.IsNullOrWhiteSpace()) GridName = $"{typeof(TDataItem).Name}Grid"; + + _gridLogName = $"[{GridName}]"; + + } + + //public Task AddDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Add); + + public Task UpdateDataItem(TDataItem dataItem) => _dataSource.Update(dataItem, true); + + public Task UpdateDataItemAsync(TDataItem dataItem) + { + _dataSource.Update(dataItem, false); + return SaveChangesToServerAsync(); + } + //public Task UpdateDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Update); + + public Task AddOrUpdateDataItem(TDataItem dataItem) => _dataSource.AddOrUpdate(dataItem, true); + + public Task RemoveDataItem(TDataItem dataItem) => _dataSource.Remove(dataItem, true); + //public Task RemoveDataItem(TDataItem dataItem, int messageTag) => PostDataToServerAsync(dataItem, messageTag, TrackingState.Remove); + + public Task RemoveDataItem(TId id) => RemoveDataItem(id, RemoveMessageTag); + + public Task RemoveDataItem(TId id, int messageTag) + { + return _dataSource.Remove(id, true); + } + + public Task ReloadDataSourceAsync() + { + return _dataSource.LoadDataSourceAsync(false); + } +} + +public class GridDataItemChangingEventArgs : GridDataItemChangedEventArgs where TDataItem : class +{ + internal GridDataItemChangingEventArgs(IMgGridBase grid, TDataItem dataItem, TrackingState trackingState) : base(grid, dataItem, trackingState) + { + } + + public bool IsCanceled { get; set; } +} + +public class GridDataItemChangedEventArgs where TDataItem : class +{ + internal GridDataItemChangedEventArgs(IMgGridBase grid, TDataItem dataItem, TrackingState trackingState) + { + Grid = grid ?? throw new ArgumentNullException(nameof(grid)); + DataItem = dataItem; + TrackingState = trackingState; + } -// public IMgGridBase Grid { get; } -// public TDataItem DataItem { get; } -// public TrackingState TrackingState { get; } -// public bool CancelStateChangeInvoke { get; set; } -//} \ No newline at end of file + public IMgGridBase Grid { get; } + public TDataItem DataItem { get; } + public TrackingState TrackingState { get; } + public bool CancelStateChangeInvoke { get; set; } +} \ No newline at end of file