123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- using InABox.Clients;
- using InABox.Core;
- using InABox.WPF;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.Drawing;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- namespace InABox.DynamicGrid;
- public class DynamicGridClientDataComponent<T> : IDynamicGridDataComponent<T>
- where T : Entity, IRemotable, IPersistent, new()
- {
- private readonly int ChunkSize = 500;
- public DynamicGrid<T> Grid { get; set; }
- public delegate void OnReloadEventHandler(object sender, Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sortby);
-
- public event OnReloadEventHandler? OnReload;
- public Column<T>[] FilterColumns;
- public DynamicGridClientDataComponent(DynamicGrid<T> grid)
- {
- Grid = grid;
- Grid.BeforeRefresh += Grid_BeforeRefresh;
- Grid.AfterRefresh += Grid_AfterRefresh;
- SetupFilterColumns();
- }
- [MemberNotNull(nameof(FilterColumns))]
- private void SetupFilterColumns()
- {
- if (typeof(T).GetCustomAttribute<AutoEntity>() is AutoEntity auto)
- {
- if (auto.Generator is not null)
- {
- var columns = auto.Generator.IDColumns;
- FilterColumns = columns.Select(x => new Column<T>(x.Property)).ToArray();
- }
- else
- {
- FilterColumns = Array.Empty<Column<T>>();
- }
- }
- else
- {
- FilterColumns = new[] { new Column<T>(x => x.ID) };
- }
- foreach (var column in FilterColumns)
- {
- Grid.AddHiddenColumn(column.Property);
- }
- }
- private CoreRow[]? SelectedBeforeRefresh;
- private void Grid_BeforeRefresh(object sender, BeforeRefreshEventArgs args)
- {
- SelectedBeforeRefresh = Grid.SelectedRows;
- }
- private void Grid_AfterRefresh(object sender, AfterRefreshEventArgs args)
- {
- if (SelectedBeforeRefresh is not null)
- {
- var selectedValues = SelectedBeforeRefresh
- .Select(x => FilterColumns.Select(c => x[c.Property]).ToList())
- .ToList();
- SelectedBeforeRefresh = null;
- var selectedRows = Grid.Data.Rows.Where(r =>
- {
- return selectedValues.Any(v =>
- {
- for (int i = 0; i < v.Count; ++i)
- {
- if (v[i]?.Equals(r[FilterColumns[i].Property]) != true)
- return false;
- }
- return true;
- });
- }).ToArray();
- Grid.SelectedRows = selectedRows;
- Grid.SelectItems(selectedRows);
- }
- }
- public Columns<T> LoadEditorColumns()
- {
- return DynamicGridUtils.LoadEditorColumns(Grid.DataColumns());
- }
- private Filter<T>? GetRowFilter(CoreRow row)
- {
- var newFilters = new Filters<T>();
- foreach (var column in FilterColumns)
- {
- newFilters.Add(new Filter<T>(column.Property).IsEqualTo(row[column.Property]));
- }
- return newFilters.Combine();
- }
- public void DeleteItems(CoreRow[] rows)
- {
- var deletes = new List<T>();
- foreach (var row in rows)
- {
- var delete = new T();
- foreach (var column in FilterColumns)
- {
- CoreUtils.SetPropertyValue(delete, column.Property, row[column.Property]);
- }
- //var delete = /* row.ToObject<TEntity>(); */
- deletes.Add(delete);
- }
- Client.Delete(deletes, "Deleted on User Request");
- }
- public T LoadItem(CoreRow row)
- {
- var id = row.Get<T, Guid>(x => x.ID);
- var filter = GetRowFilter(row);//new Filter<TEntity>(x => x.ID).IsEqualTo(id);
- return Client.Query(filter, LoadEditorColumns()).ToObjects<T>().FirstOrDefault()
- ?? throw new Exception($"No {typeof(T).Name} with ID {id}");
- }
- public T[] LoadItems(CoreRow[] rows)
- {
- Filter<T>? filter = null;
- var results = new List<T>();
- for (var i = 0; i < rows.Length; i += ChunkSize)
- {
- var chunk = rows.Skip(i).Take(ChunkSize);
- foreach (var row in chunk)
- {
- var newFilter = GetRowFilter(row);
- if (newFilter is not null)
- {
- //var id = row.Get<TEntity, Guid>(x => x.ID);
- if (filter is null)
- filter = newFilter;//new Filter<TEntity>(x => x.ID).IsEqualTo(id);
- else
- filter = filter.Or(newFilter);//.Or(x => x.ID).IsEqualTo(id);
- }
- }
- var columns = LoadEditorColumns(); // new Columns<TEntity>().Default(ColumnType.IncludeOptional, ColumnType.IncludeForeignKeys, ColumnType.IncludeUserProperties);
- var data = Client.Query(filter, columns);
- results.AddRange(data.ToObjects<T>());
- }
- return results.ToArray();
- }
- public void SaveItem(T item)
- {
- Client.Save(item, "Edited by User");
- }
- public void SaveItems(T[] items)
- {
- Client.Save(items, "Edited by User");
- }
- public void Reload(
- Filters<T> criteria, Columns<T> columns, SortOrder<T>? sort,
- CancellationToken token, Action<QueryResult> action)
- {
- OnReload?.Invoke(this, criteria, columns, ref sort);
- if(Grid.Options.PageSize > 0)
- {
- var inSort = sort;
- Task.Run(() =>
- {
-
- var page = CoreRange.Database(Grid.Options.PageSize);
- var filter = criteria.Combine();
-
- while (!token.IsCancellationRequested)
- {
- try
- {
- var data = Client.Query(filter, columns, inSort, page);
- data.Offset = page.Offset;
- if (token.IsCancellationRequested)
- {
- break;
- }
- var paged = data.Rows.Count == page.Limit;
- action(new(data, paged));
- if (!paged)
- break;
-
- // Proposal - Let's slow it down a bit to enhance UI responsiveness?
- Thread.Sleep(100);
-
- page.Next();
- }
- catch (Exception e)
- {
- action(new(e));
- break;
- }
- }
- }, token);
- }
- else
- {
- Client.Query(criteria.Combine(), columns, sort, (data, e) => action(data is not null ? new(data) : new(e!)));
- }
- }
- }
|