|
@@ -10,297 +10,296 @@ using System.Threading.Tasks;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
|
|
-namespace InABox.DynamicGrid
|
|
|
|
|
|
+namespace InABox.DynamicGrid;
|
|
|
|
+
|
|
|
|
+public abstract class DynamicManyToManyCrossTab<TManyToMany, TRow, TColumn> : DynamicGrid<TRow>
|
|
|
|
+ where TManyToMany : Entity, IRemotable, IPersistent, new()
|
|
|
|
+ where TRow : Entity, IRemotable, IPersistent, new()
|
|
|
|
+ where TColumn : Entity, IRemotable, IPersistent, new()
|
|
{
|
|
{
|
|
- public abstract class DynamicManyToManyCrossTab<TManyToMany, TRow, TColumn> : DynamicGrid<TRow>
|
|
|
|
- where TManyToMany : Entity, IRemotable, IPersistent, new()
|
|
|
|
- where TRow : Entity, IRemotable, IPersistent, new()
|
|
|
|
- where TColumn : Entity, IRemotable, IPersistent, new()
|
|
|
|
|
|
+ private static readonly BitmapImage tick = Wpf.Resources.tick.AsBitmapImage();
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Property on <typeparamref name="TManyToMany"/> which is an <see cref="EntityLink{T}"/> for <typeparamref name="TRow"/>.
|
|
|
|
+ /// </summary>
|
|
|
|
+ private readonly PropertyInfo rowProperty;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Property on <typeparamref name="TManyToMany"/> which is an <see cref="EntityLink{T}"/> for <typeparamref name="TColumn"/>.
|
|
|
|
+ /// </summary>
|
|
|
|
+ private readonly PropertyInfo columnProperty;
|
|
|
|
+
|
|
|
|
+ private CoreTable? ColumnData;
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// {ColumnID : { RowID }}
|
|
|
|
+ /// </summary>
|
|
|
|
+ private Dictionary<Guid, Dictionary<Guid, TManyToMany>>? ManyToManyData;
|
|
|
|
+
|
|
|
|
+ public DynamicManyToManyCrossTab()
|
|
{
|
|
{
|
|
- private static readonly BitmapImage tick = Wpf.Resources.tick.AsBitmapImage();
|
|
|
|
-
|
|
|
|
- /// <summary>
|
|
|
|
- /// Property on <typeparamref name="TManyToMany"/> which is an <see cref="EntityLink{T}"/> for <typeparamref name="TRow"/>.
|
|
|
|
- /// </summary>
|
|
|
|
- private readonly PropertyInfo rowProperty;
|
|
|
|
- /// <summary>
|
|
|
|
- /// Property on <typeparamref name="TManyToMany"/> which is an <see cref="EntityLink{T}"/> for <typeparamref name="TColumn"/>.
|
|
|
|
- /// </summary>
|
|
|
|
- private readonly PropertyInfo columnProperty;
|
|
|
|
-
|
|
|
|
- private CoreTable? ColumnData;
|
|
|
|
- /// <summary>
|
|
|
|
- /// {ColumnID : { RowID }}
|
|
|
|
- /// </summary>
|
|
|
|
- private Dictionary<Guid, Dictionary<Guid, TManyToMany>>? ManyToManyData;
|
|
|
|
-
|
|
|
|
- public DynamicManyToManyCrossTab()
|
|
|
|
- {
|
|
|
|
- rowProperty = CoreUtils.GetManyToManyThisProperty(typeof(TManyToMany), typeof(TRow));
|
|
|
|
- columnProperty = CoreUtils.GetManyToManyThisProperty(typeof(TManyToMany), typeof(TColumn));
|
|
|
|
-
|
|
|
|
- HeaderHeight = 125;
|
|
|
|
- }
|
|
|
|
|
|
+ rowProperty = CoreUtils.GetManyToManyThisProperty(typeof(TManyToMany), typeof(TRow));
|
|
|
|
+ columnProperty = CoreUtils.GetManyToManyThisProperty(typeof(TManyToMany), typeof(TColumn));
|
|
|
|
|
|
- protected override void Init()
|
|
|
|
- {
|
|
|
|
- }
|
|
|
|
|
|
+ HeaderHeight = 125;
|
|
|
|
+ }
|
|
|
|
|
|
- protected override void DoReconfigure(FluentList<DynamicGridOption> options)
|
|
|
|
- {
|
|
|
|
- options.Clear();
|
|
|
|
- }
|
|
|
|
|
|
+ protected override void Init()
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
|
|
- /// <summary>
|
|
|
|
- /// Load the required columns for <typeparamref name="TRow"/>.
|
|
|
|
- /// </summary>
|
|
|
|
- protected abstract DynamicGridColumns LoadRowColumns();
|
|
|
|
|
|
+ protected override void DoReconfigure(FluentList<DynamicGridOption> options)
|
|
|
|
+ {
|
|
|
|
+ options.Clear();
|
|
|
|
+ }
|
|
|
|
|
|
- protected abstract Columns<TColumn>? LoadColumnColumns();
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Load the required columns for <typeparamref name="TRow"/>.
|
|
|
|
+ /// </summary>
|
|
|
|
+ protected abstract DynamicGridColumns LoadRowColumns();
|
|
|
|
|
|
- protected abstract SortOrder<TColumn>? LoadColumnSort();
|
|
|
|
|
|
+ protected abstract Columns<TColumn>? LoadColumnColumns();
|
|
|
|
|
|
- protected abstract string FormatColumnHeader(CoreRow row);
|
|
|
|
|
|
+ protected abstract SortOrder<TColumn>? LoadColumnSort();
|
|
|
|
|
|
- protected virtual Filter<TRow>? RowFilter() => null;
|
|
|
|
|
|
+ protected abstract string FormatColumnHeader(CoreRow row);
|
|
|
|
|
|
- protected virtual Filter<TColumn>? ColumnFilter() => null;
|
|
|
|
|
|
+ protected virtual Filter<TRow>? RowFilter() => null;
|
|
|
|
|
|
- protected override DynamicGridColumns LoadColumns()
|
|
|
|
- {
|
|
|
|
- var columns = LoadRowColumns();
|
|
|
|
|
|
+ protected virtual Filter<TColumn>? ColumnFilter() => null;
|
|
|
|
|
|
- var client = Client.Create(typeof(TColumn));
|
|
|
|
|
|
+ protected override DynamicGridColumns LoadColumns()
|
|
|
|
+ {
|
|
|
|
+ var columns = LoadRowColumns();
|
|
|
|
|
|
- var columnColumns = new Columns<TColumn>(x => x.ID);
|
|
|
|
- if(LoadColumnColumns() is Columns<TColumn> extra)
|
|
|
|
- {
|
|
|
|
- foreach(var col in extra.GetColumns())
|
|
|
|
- {
|
|
|
|
- columnColumns.Add(col);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ var client = Client.Create(typeof(TColumn));
|
|
|
|
|
|
- ColumnData = Client.Query(ColumnFilter(), columnColumns, LoadColumnSort());
|
|
|
|
- ActionColumns.Clear();
|
|
|
|
- foreach(var columnRow in ColumnData.Rows)
|
|
|
|
|
|
+ var columnColumns = new Columns<TColumn>(x => x.ID);
|
|
|
|
+ if(LoadColumnColumns() is Columns<TColumn> extra)
|
|
|
|
+ {
|
|
|
|
+ foreach(var col in extra.GetColumns())
|
|
{
|
|
{
|
|
- var colID = columnRow.Get<TColumn, Guid>(x => x.ID);
|
|
|
|
- ActionColumns.Add(new DynamicImageColumn(
|
|
|
|
- (row) =>
|
|
|
|
- {
|
|
|
|
- if (row is null || ManyToManyData is null) return null;
|
|
|
|
- if(ManyToManyData.TryGetValue(colID, out var rowSet))
|
|
|
|
- {
|
|
|
|
- var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
- if (rowSet.ContainsKey(rowID))
|
|
|
|
- {
|
|
|
|
- return tick;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
- },
|
|
|
|
- (row) =>
|
|
|
|
- {
|
|
|
|
- if (row is null) return false;
|
|
|
|
- var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
- return CellClick(colID, rowID);
|
|
|
|
- }
|
|
|
|
- )
|
|
|
|
- {
|
|
|
|
- HeaderText = FormatColumnHeader(columnRow),
|
|
|
|
- ContextMenu = (rows) =>
|
|
|
|
- {
|
|
|
|
- var row = rows?.FirstOrDefault();
|
|
|
|
- if (row is null) return null;
|
|
|
|
- var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
- return CellMenu(colID, rowID);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ columnColumns.Add(col);
|
|
}
|
|
}
|
|
-
|
|
|
|
- return columns;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- private ContextMenu? CellMenu(Guid colID, Guid rowID)
|
|
|
|
|
|
+ ColumnData = Client.Query(ColumnFilter(), columnColumns, LoadColumnSort());
|
|
|
|
+ ActionColumns.Clear();
|
|
|
|
+ foreach(var columnRow in ColumnData.Rows)
|
|
{
|
|
{
|
|
- if (ManyToManyData is null) return null;
|
|
|
|
-
|
|
|
|
- var menu = new ContextMenu();
|
|
|
|
-
|
|
|
|
- if (ManyToManyData.TryGetValue(colID, out var rowSet)
|
|
|
|
- && rowSet.TryGetValue(rowID, out var obj))
|
|
|
|
- {
|
|
|
|
- if (Security.CanEdit<TManyToMany>() && CanEditCell(obj))
|
|
|
|
|
|
+ var colID = columnRow.Get<TColumn, Guid>(x => x.ID);
|
|
|
|
+ ActionColumns.Add(new DynamicImageColumn(
|
|
|
|
+ (row) =>
|
|
{
|
|
{
|
|
- menu.AddItem("Edit Item", Wpf.Resources.pencil, obj, (obj) =>
|
|
|
|
|
|
+ if (row is null || ManyToManyData is null) return null;
|
|
|
|
+ if(ManyToManyData.TryGetValue(colID, out var rowSet))
|
|
{
|
|
{
|
|
- if (EditCell(obj))
|
|
|
|
|
|
+ var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
+ if (rowSet.ContainsKey(rowID))
|
|
{
|
|
{
|
|
- Refresh(false, true);
|
|
|
|
|
|
+ return tick;
|
|
}
|
|
}
|
|
- });
|
|
|
|
- }
|
|
|
|
- if (Security.CanDelete<TManyToMany>())
|
|
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ },
|
|
|
|
+ (row) =>
|
|
{
|
|
{
|
|
- menu.AddItem("Delete Item", Wpf.Resources.delete, obj, DeleteCell);
|
|
|
|
|
|
+ if (row is null) return false;
|
|
|
|
+ var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
+ return CellClick(colID, rowID);
|
|
}
|
|
}
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+ )
|
|
{
|
|
{
|
|
- if (Security.CanEdit<TManyToMany>())
|
|
|
|
|
|
+ HeaderText = FormatColumnHeader(columnRow),
|
|
|
|
+ ContextMenu = (rows) =>
|
|
{
|
|
{
|
|
- menu.AddItem("Create Item", Wpf.Resources.add, (colID, rowID), CreateCell);
|
|
|
|
|
|
+ var row = rows?.FirstOrDefault();
|
|
|
|
+ if (row is null) return null;
|
|
|
|
+ var rowID = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
+ return CellMenu(colID, rowID);
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return columns;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private ContextMenu? CellMenu(Guid colID, Guid rowID)
|
|
|
|
+ {
|
|
|
|
+ if (ManyToManyData is null) return null;
|
|
|
|
+
|
|
|
|
+ var menu = new ContextMenu();
|
|
|
|
|
|
- if(menu.Items.Count > 0)
|
|
|
|
|
|
+ if (ManyToManyData.TryGetValue(colID, out var rowSet)
|
|
|
|
+ && rowSet.TryGetValue(rowID, out var obj))
|
|
|
|
+ {
|
|
|
|
+ if (Security.CanEdit<TManyToMany>() && CanEditCell(obj))
|
|
{
|
|
{
|
|
- return menu;
|
|
|
|
|
|
+ menu.AddItem("Edit Item", Wpf.Resources.pencil, obj, (obj) =>
|
|
|
|
+ {
|
|
|
|
+ if (EditCell(obj))
|
|
|
|
+ {
|
|
|
|
+ Refresh(false, true);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
}
|
|
}
|
|
- else
|
|
|
|
|
|
+ if (Security.CanDelete<TManyToMany>())
|
|
{
|
|
{
|
|
- return null;
|
|
|
|
|
|
+ menu.AddItem("Delete Item", Wpf.Resources.delete, obj, DeleteCell);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- private void CreateCell((Guid colID, Guid rowID) obj)
|
|
|
|
|
|
+ else
|
|
{
|
|
{
|
|
- var manyToMany = CreateManyToMany(obj.rowID, obj.colID);
|
|
|
|
- if (SaveManyToMany(manyToMany))
|
|
|
|
|
|
+ if (Security.CanEdit<TManyToMany>())
|
|
{
|
|
{
|
|
- Refresh(false, true);
|
|
|
|
|
|
+ menu.AddItem("Create Item", Wpf.Resources.add, (colID, rowID), CreateCell);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void DeleteCell(TManyToMany obj)
|
|
|
|
|
|
+ if(menu.Items.Count > 0)
|
|
{
|
|
{
|
|
- if (DeleteManyToMany(obj))
|
|
|
|
- {
|
|
|
|
- Refresh(false, true);
|
|
|
|
- }
|
|
|
|
|
|
+ return menu;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void CreateCell((Guid colID, Guid rowID) obj)
|
|
|
|
+ {
|
|
|
|
+ var manyToMany = CreateManyToMany(obj.rowID, obj.colID);
|
|
|
|
+ if (SaveManyToMany(manyToMany))
|
|
|
|
+ {
|
|
|
|
+ Refresh(false, true);
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- protected virtual bool CanEditCell(TManyToMany obj) => false;
|
|
|
|
-
|
|
|
|
- /// <summary>
|
|
|
|
- /// Code to edit a <typeparamref name="TManyToMany"/> cell; note that this <b>must not</b> allow for changing either
|
|
|
|
- /// the <typeparamref name="TColumn"/> or the <typeparamref name="TRow"/>, otherwise we would easily get duplicate <typeparamref name="TManyToMany"/>s.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <remarks>
|
|
|
|
- /// This method should also save the object.
|
|
|
|
- /// </remarks>
|
|
|
|
- /// <param name="obj"></param>
|
|
|
|
- protected virtual bool EditCell(TManyToMany obj)
|
|
|
|
|
|
+ private void DeleteCell(TManyToMany obj)
|
|
|
|
+ {
|
|
|
|
+ if (DeleteManyToMany(obj))
|
|
{
|
|
{
|
|
- return false;
|
|
|
|
|
|
+ Refresh(false, true);
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- private bool CellClick(Guid columnID, Guid rowID)
|
|
|
|
|
|
+ protected virtual bool CanEditCell(TManyToMany obj) => false;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Code to edit a <typeparamref name="TManyToMany"/> cell; note that this <b>must not</b> allow for changing either
|
|
|
|
+ /// the <typeparamref name="TColumn"/> or the <typeparamref name="TRow"/>, otherwise we would easily get duplicate <typeparamref name="TManyToMany"/>s.
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <remarks>
|
|
|
|
+ /// This method should also save the object.
|
|
|
|
+ /// </remarks>
|
|
|
|
+ /// <param name="obj"></param>
|
|
|
|
+ protected virtual bool EditCell(TManyToMany obj)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private bool CellClick(Guid columnID, Guid rowID)
|
|
|
|
+ {
|
|
|
|
+ if (ManyToManyData is null) return false;
|
|
|
|
+ if (ManyToManyData.TryGetValue(columnID, out var rowSet)
|
|
|
|
+ && rowSet.TryGetValue(rowID, out var obj))
|
|
{
|
|
{
|
|
- if (ManyToManyData is null) return false;
|
|
|
|
- if (ManyToManyData.TryGetValue(columnID, out var rowSet)
|
|
|
|
- && rowSet.TryGetValue(rowID, out var obj))
|
|
|
|
|
|
+ if (Security.CanDelete<TManyToMany>())
|
|
{
|
|
{
|
|
- if (Security.CanDelete<TManyToMany>())
|
|
|
|
- {
|
|
|
|
- return DeleteManyToMany(obj);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ return DeleteManyToMany(obj);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- if (Security.CanEdit<TManyToMany>())
|
|
|
|
- {
|
|
|
|
- obj = CreateManyToMany(rowID, columnID);
|
|
|
|
- return SaveManyToMany(obj);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- protected virtual TManyToMany CreateManyToMany(Guid rowID, Guid columnID)
|
|
|
|
|
|
+ else
|
|
{
|
|
{
|
|
- var item = new TManyToMany();
|
|
|
|
- (rowProperty.GetValue(item) as IEntityLink)!.ID = rowID;
|
|
|
|
- (columnProperty.GetValue(item) as IEntityLink)!.ID = columnID;
|
|
|
|
- return item;
|
|
|
|
|
|
+ if (Security.CanEdit<TManyToMany>())
|
|
|
|
+ {
|
|
|
|
+ obj = CreateManyToMany(rowID, columnID);
|
|
|
|
+ return SaveManyToMany(obj);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- protected virtual bool SaveManyToMany(TManyToMany obj)
|
|
|
|
- {
|
|
|
|
- Client.Save(obj, "Edited by user");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ protected virtual TManyToMany CreateManyToMany(Guid rowID, Guid columnID)
|
|
|
|
+ {
|
|
|
|
+ var item = new TManyToMany();
|
|
|
|
+ (rowProperty.GetValue(item) as IEntityLink)!.ID = rowID;
|
|
|
|
+ (columnProperty.GetValue(item) as IEntityLink)!.ID = columnID;
|
|
|
|
+ return item;
|
|
|
|
+ }
|
|
|
|
|
|
- protected virtual bool DeleteManyToMany(TManyToMany obj)
|
|
|
|
- {
|
|
|
|
- Client.Delete(obj, "Deleted by user");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ protected virtual bool SaveManyToMany(TManyToMany obj)
|
|
|
|
+ {
|
|
|
|
+ Client.Save(obj, "Edited by user");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- protected override void Reload(Filters<TRow> criteria, Columns<TRow> columns, ref SortOrder<TRow>? sort, Action<CoreTable?, Exception?> action)
|
|
|
|
- {
|
|
|
|
- var filter = criteria.Add(RowFilter()).Combine();
|
|
|
|
|
|
+ protected virtual bool DeleteManyToMany(TManyToMany obj)
|
|
|
|
+ {
|
|
|
|
+ Client.Delete(obj, "Deleted by user");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- var manyToManyColumns = new Columns<TManyToMany>(x => x.ID);
|
|
|
|
- manyToManyColumns.Add(rowProperty.Name + ".ID").Add(columnProperty.Name + ".ID");
|
|
|
|
|
|
+ protected override void Reload(Filters<TRow> criteria, Columns<TRow> columns, ref SortOrder<TRow>? sort, Action<CoreTable?, Exception?> action)
|
|
|
|
+ {
|
|
|
|
+ var filter = criteria.Add(RowFilter()).Combine();
|
|
|
|
+
|
|
|
|
+ var manyToManyColumns = new Columns<TManyToMany>(x => x.ID);
|
|
|
|
+ manyToManyColumns.Add(rowProperty.Name + ".ID").Add(columnProperty.Name + ".ID");
|
|
|
|
|
|
- Client.QueryMultiple(
|
|
|
|
- (results, e) =>
|
|
|
|
|
|
+ Client.QueryMultiple(
|
|
|
|
+ (results, e) =>
|
|
|
|
+ {
|
|
|
|
+ if(e is not null)
|
|
|
|
+ {
|
|
|
|
+ action(null, e);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
{
|
|
{
|
|
- if(e is not null)
|
|
|
|
|
|
+ var manyToManyTable = results!.Get<TManyToMany>();
|
|
|
|
+
|
|
|
|
+ ManyToManyData = new Dictionary<Guid, Dictionary<Guid, TManyToMany>>();
|
|
|
|
+ foreach(var row in manyToManyTable.Rows)
|
|
{
|
|
{
|
|
- action(null, e);
|
|
|
|
|
|
+ var obj = row.ToObject<TManyToMany>();
|
|
|
|
+ var rowID = (rowProperty.GetValue(obj) as IEntityLink)!.ID;
|
|
|
|
+ var colID = (columnProperty.GetValue(obj) as IEntityLink)!.ID;
|
|
|
|
+ var rowSet = ManyToManyData.GetValueOrAdd(colID);
|
|
|
|
+ rowSet[rowID] = obj;
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- var manyToManyTable = results!.Get<TManyToMany>();
|
|
|
|
|
|
|
|
- ManyToManyData = new Dictionary<Guid, Dictionary<Guid, TManyToMany>>();
|
|
|
|
- foreach(var row in manyToManyTable.Rows)
|
|
|
|
- {
|
|
|
|
- var obj = row.ToObject<TManyToMany>();
|
|
|
|
- var rowID = (rowProperty.GetValue(obj) as IEntityLink)!.ID;
|
|
|
|
- var colID = (columnProperty.GetValue(obj) as IEntityLink)!.ID;
|
|
|
|
- var rowSet = ManyToManyData.GetValueOrAdd(colID);
|
|
|
|
- rowSet[rowID] = obj;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- action(results!.Get<TRow>(), null);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- new KeyedQueryDef<TRow>(filter, columns, sort),
|
|
|
|
- new KeyedQueryDef<TManyToMany>(
|
|
|
|
- new Filter<TManyToMany>(rowProperty.Name + ".ID").InQuery(filter, x => x.ID)
|
|
|
|
- .And(columnProperty.Name + ".ID").InQuery(ColumnFilter(), x => x.ID),
|
|
|
|
- manyToManyColumns));
|
|
|
|
- }
|
|
|
|
|
|
+ action(results!.Get<TRow>(), null);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ new KeyedQueryDef<TRow>(filter, columns, sort),
|
|
|
|
+ new KeyedQueryDef<TManyToMany>(
|
|
|
|
+ new Filter<TManyToMany>(rowProperty.Name + ".ID").InQuery(filter, x => x.ID)
|
|
|
|
+ .And(columnProperty.Name + ".ID").InQuery(ColumnFilter(), x => x.ID),
|
|
|
|
+ manyToManyColumns));
|
|
|
|
+ }
|
|
|
|
|
|
- public override void SaveItem(TRow item)
|
|
|
|
- {
|
|
|
|
- // Never should get called.
|
|
|
|
- }
|
|
|
|
|
|
+ public override void SaveItem(TRow item)
|
|
|
|
+ {
|
|
|
|
+ // Never should get called.
|
|
|
|
+ }
|
|
|
|
|
|
- public override void DeleteItems(params CoreRow[] rows)
|
|
|
|
- {
|
|
|
|
- // Never should get called.
|
|
|
|
- }
|
|
|
|
|
|
+ public override void DeleteItems(params CoreRow[] rows)
|
|
|
|
+ {
|
|
|
|
+ // Never should get called.
|
|
|
|
+ }
|
|
|
|
|
|
- public override TRow LoadItem(CoreRow row)
|
|
|
|
- {
|
|
|
|
- var id = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
- return Client.Query(
|
|
|
|
- new Filter<TRow>(x => x.ID).IsEqualTo(id),
|
|
|
|
- DynamicGridUtils.LoadEditorColumns(DataColumns()))
|
|
|
|
- .ToObjects<TRow>()
|
|
|
|
- .FirstOrDefault() ?? throw new Exception($"No {typeof(TRow).Name} with ID {id}");
|
|
|
|
- }
|
|
|
|
|
|
+ public override TRow LoadItem(CoreRow row)
|
|
|
|
+ {
|
|
|
|
+ var id = row.Get<TRow, Guid>(x => x.ID);
|
|
|
|
+ return Client.Query(
|
|
|
|
+ new Filter<TRow>(x => x.ID).IsEqualTo(id),
|
|
|
|
+ DynamicGridUtils.LoadEditorColumns(DataColumns()))
|
|
|
|
+ .ToObjects<TRow>()
|
|
|
|
+ .FirstOrDefault() ?? throw new Exception($"No {typeof(TRow).Name} with ID {id}");
|
|
}
|
|
}
|
|
}
|
|
}
|