|
@@ -25,6 +25,8 @@ using Syncfusion.UI.Xaml.TreeGrid.Filtering;
|
|
|
using Syncfusion.UI.Xaml.TreeGrid.Cells;
|
|
|
using System.Windows.Controls.Primitives;
|
|
|
using NPOI.OpenXmlFormats.Dml;
|
|
|
+using System.Windows.Navigation;
|
|
|
+using NavigationMode = Syncfusion.UI.Xaml.Grid.NavigationMode;
|
|
|
|
|
|
namespace InABox.DynamicGrid;
|
|
|
|
|
@@ -43,7 +45,7 @@ public enum DynamicTreeGridExpandMode
|
|
|
None
|
|
|
}
|
|
|
|
|
|
-public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynamicGridGridUIComponent<T>
|
|
|
+public class DynamicGridTreeUIComponent<T, TKey> : IDynamicGridUIComponent<T>, IDynamicGridGridUIComponent<T>
|
|
|
where T : BaseObject, new()
|
|
|
{
|
|
|
private IDynamicGridUIComponentParent<T> _parent;
|
|
@@ -60,20 +62,32 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
CellFontStyleConverter = new DynamicGridCellStyleConverter<System.Windows.FontStyle?>(Parent, GetCellFontStyle);
|
|
|
CellFontWeightConverter = new DynamicGridCellStyleConverter<System.Windows.FontWeight?>(Parent, GetCellFontWeight);
|
|
|
|
|
|
- Parent.AddHiddenColumn(IDColumn.Property);
|
|
|
- Parent.AddHiddenColumn(ParentColumn.Property);
|
|
|
+ if(IDColumn is not null)
|
|
|
+ {
|
|
|
+ Parent.AddHiddenColumn(IDColumn.Property);
|
|
|
+ }
|
|
|
+ if(ParentColumn is not null)
|
|
|
+ {
|
|
|
+ Parent.AddHiddenColumn(ParentColumn.Property);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private Column<T> IDColumn;
|
|
|
- private Column<T> ParentColumn;
|
|
|
+ private readonly TKey NullKey;
|
|
|
+
|
|
|
+ private readonly Func<CoreRow, TKey>? IDKey;
|
|
|
+ private readonly Func<CoreRow, TKey>? ParentKey;
|
|
|
+ private readonly Action<T, TKey>? SetParentKey;
|
|
|
+
|
|
|
+ private readonly Column<T>? IDColumn;
|
|
|
+ private readonly Column<T>? ParentColumn;
|
|
|
|
|
|
private ContextMenu _menu;
|
|
|
private SfTreeGrid _tree;
|
|
|
private Grid _summaryRow;
|
|
|
private readonly ContextMenu ColumnsMenu;
|
|
|
|
|
|
- public event OnContextMenuOpening OnContextMenuOpening;
|
|
|
+ public event OnContextMenuOpening<TKey> OnContextMenuOpening;
|
|
|
|
|
|
FrameworkElement IDynamicGridUIComponent<T>.Control => _tree;
|
|
|
|
|
@@ -185,11 +199,23 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
private DynamicGridCellStyleConverter<System.Windows.FontStyle?> CellFontStyleConverter;
|
|
|
private DynamicGridCellStyleConverter<System.Windows.FontWeight?> CellFontWeightConverter;
|
|
|
|
|
|
- public DynamicGridTreeUIComponent(Expression<Func<T, Guid>> idColumn, Expression<Func<T, Guid>> parentIDColumn)
|
|
|
+ public DynamicGridTreeUIComponent(Func<CoreRow, TKey> idKey, Func<CoreRow, TKey> parentKey, TKey nullKey, Action<T, TKey> setParentKey): this()
|
|
|
+ {
|
|
|
+ IDKey = idKey;
|
|
|
+ ParentKey = parentKey;
|
|
|
+ NullKey = nullKey;
|
|
|
+ SetParentKey = setParentKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ public DynamicGridTreeUIComponent(Expression<Func<T, TKey>> idColumn, Expression<Func<T, TKey>> parentIDColumn, TKey nullKey): this()
|
|
|
{
|
|
|
IDColumn = new Column<T>(CoreUtils.GetFullPropertyName(idColumn, "."));
|
|
|
ParentColumn = new Column<T>(CoreUtils.GetFullPropertyName(parentIDColumn, "."));
|
|
|
+ NullKey = nullKey;
|
|
|
+ }
|
|
|
|
|
|
+ private DynamicGridTreeUIComponent()
|
|
|
+ {
|
|
|
ColumnsMenu = new ContextMenu();
|
|
|
ColumnsMenu.Opened += ColumnsMenu_ContextMenuOpening;
|
|
|
|
|
@@ -219,7 +245,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
_menu = new ContextMenu();
|
|
|
var additem = new MenuItem() { Header = "Add Child Folder" };
|
|
|
- additem.Click += (o, e) => { DoAddItem((_tree.SelectedItem as CoreTreeNode)!.ID, true); };
|
|
|
+ additem.Click += (o, e) => { DoAddItem((_tree.SelectedItem as CoreTreeNode<TKey>)!.ID, true); };
|
|
|
_menu.Items.Add(additem);
|
|
|
|
|
|
_tree.ContextMenuOpening += _tree_ContextMenuOpening;
|
|
@@ -378,9 +404,9 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private class TreeGridSelectionControllerExt(SfTreeGrid treeGrid, DynamicGridTreeUIComponent<T> grid) : TreeGridRowSelectionController(treeGrid)
|
|
|
+ private class TreeGridSelectionControllerExt(SfTreeGrid treeGrid, DynamicGridTreeUIComponent<T, TKey> grid) : TreeGridRowSelectionController(treeGrid)
|
|
|
{
|
|
|
- private DynamicGridTreeUIComponent<T> Grid = grid;
|
|
|
+ private DynamicGridTreeUIComponent<T, TKey> Grid = grid;
|
|
|
|
|
|
public override bool HandleKeyDown(KeyEventArgs args)
|
|
|
{
|
|
@@ -398,7 +424,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
#region Public Interface
|
|
|
|
|
|
- public IEnumerable<CoreRow> GetChildren(Guid id)
|
|
|
+ public IEnumerable<CoreRow> GetChildren(TKey id)
|
|
|
{
|
|
|
return Nodes.GetChildren(id).Select(x => MapRow(x.Row)).NotNull();
|
|
|
}
|
|
@@ -407,12 +433,12 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
#region Input
|
|
|
|
|
|
- private CoreTreeNode? GetNodeFromIndex(int rowIndex)
|
|
|
+ private CoreTreeNode<TKey>? GetNodeFromIndex(int rowIndex)
|
|
|
{
|
|
|
// Syncfusion has given us the row index, so it also will give us the correct row, after sorting.
|
|
|
// Hence, here we use the syncfusion DataGrid.GetRecordAtRowIndex, which *should* always return a DataRowView.
|
|
|
var row = _tree.GetNodeAtRowIndex(rowIndex);
|
|
|
- return row.Item as CoreTreeNode;
|
|
|
+ return row.Item as CoreTreeNode<TKey>;
|
|
|
}
|
|
|
|
|
|
private CoreRow? GetRowFromIndex(int rowIndex)
|
|
@@ -486,7 +512,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
- return _tree.SelectedItems.OfType<CoreTreeNode>()
|
|
|
+ return _tree.SelectedItems.OfType<CoreTreeNode<TKey>>()
|
|
|
.Select(x => GetRow(x)).NotNull().ToArray();
|
|
|
}
|
|
|
set
|
|
@@ -494,7 +520,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
_tree.SelectedItems.Clear();
|
|
|
foreach (var row in value)
|
|
|
{
|
|
|
- _tree.SelectedItems.Add(Nodes.Find(row.Get<Guid>(IDColumn.Property)));
|
|
|
+ _tree.SelectedItems.Add(Nodes.Find(GetIDKey(row)));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -821,7 +847,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
_menu.Items.Clear();
|
|
|
if (OnContextMenuOpening is not null)
|
|
|
{
|
|
|
- OnContextMenuOpening.Invoke((_tree.SelectedItem as CoreTreeNode)!, _menu);
|
|
|
+ OnContextMenuOpening.Invoke((_tree.SelectedItem as CoreTreeNode<TKey>)!, _menu);
|
|
|
if(_menu.Items.Count == 0)
|
|
|
{
|
|
|
e.Handled = true;
|
|
@@ -831,7 +857,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
{
|
|
|
if (Parent.Options.AddRows)
|
|
|
{
|
|
|
- _menu.AddItem("Add Item", null, (_tree.SelectedItem as CoreTreeNode)!.ID, (id) => DoAddItem(id, true));
|
|
|
+ _menu.AddItem("Add Item", null, (_tree.SelectedItem as CoreTreeNode<TKey>)!.ID, (id) => DoAddItem(id, true));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -840,14 +866,14 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
#region CRUD
|
|
|
|
|
|
- protected T DoCreateItem(Guid parent)
|
|
|
+ protected T DoCreateItem(TKey parent)
|
|
|
{
|
|
|
var result = Parent.CreateItem();
|
|
|
- CoreUtils.SetPropertyValue(result, ParentColumn.Property, parent);
|
|
|
+ SetParent(result, parent);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- protected void DoAddItem(Guid id, bool edit)
|
|
|
+ protected void DoAddItem(TKey id, bool edit)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
@@ -877,7 +903,50 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
#region Rows
|
|
|
|
|
|
- private CoreRow? GetRow(CoreTreeNode? node)
|
|
|
+ private TKey GetIDKey(CoreRow row)
|
|
|
+ {
|
|
|
+ if(IDColumn is not null)
|
|
|
+ {
|
|
|
+ return row.Get<TKey>(IDColumn.Property);
|
|
|
+ }
|
|
|
+ else if(IDKey is not null)
|
|
|
+ {
|
|
|
+ return IDKey(row);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return NullKey;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ private TKey GetParentKey(CoreRow row)
|
|
|
+ {
|
|
|
+ if(ParentColumn is not null)
|
|
|
+ {
|
|
|
+ return row.Get<TKey>(ParentColumn.Property);
|
|
|
+ }
|
|
|
+ else if(ParentKey is not null)
|
|
|
+ {
|
|
|
+ return ParentKey(row);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return NullKey;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SetParent(T obj, TKey key)
|
|
|
+ {
|
|
|
+ if(ParentColumn is not null)
|
|
|
+ {
|
|
|
+ ParentColumn.PropertyDefinition.Setter()(obj, key);
|
|
|
+ }
|
|
|
+ else if(SetParentKey is not null)
|
|
|
+ {
|
|
|
+ SetParentKey(obj, key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private CoreRow? GetRow(CoreTreeNode<TKey>? node)
|
|
|
{
|
|
|
return MapRow(node?.Row);
|
|
|
}
|
|
@@ -892,7 +961,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
return Parent.Data.Rows[row.Index];
|
|
|
}
|
|
|
|
|
|
- private CoreTreeNode? GetNode(CoreRow row)
|
|
|
+ private CoreTreeNode<TKey>? GetNode(CoreRow row)
|
|
|
{
|
|
|
if (_innerTable is null || row.Index < 0 || row.Index >= _innerTable.Rows.Count) return null;
|
|
|
|
|
@@ -903,7 +972,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public CoreRow[] GetVisibleRows()
|
|
|
{
|
|
|
- return _tree.View?.Nodes.Select(x => MapRow((x.Item as CoreTreeNode)?.Row)).NotNull().ToArray() ?? new CoreRow[] { };
|
|
|
+ return _tree.View?.Nodes.Select(x => MapRow((x.Item as CoreTreeNode<TKey>)?.Row)).NotNull().ToArray() ?? new CoreRow[] { };
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
@@ -967,15 +1036,15 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public class TemplateColumnSelector(DynamicGridTreeUIComponent<T> parent, Func<CoreRow, FrameworkElement?> dataTemplate) : DataTemplateSelector
|
|
|
+ public class TemplateColumnSelector(DynamicGridTreeUIComponent<T, TKey> parent, Func<CoreRow, FrameworkElement?> dataTemplate) : DataTemplateSelector
|
|
|
{
|
|
|
public Func<CoreRow, FrameworkElement?> DataTemplate { get; init; } = dataTemplate;
|
|
|
|
|
|
- public DynamicGridTreeUIComponent<T> Parent { get; init; } = parent;
|
|
|
+ public DynamicGridTreeUIComponent<T, TKey> Parent { get; init; } = parent;
|
|
|
|
|
|
public override DataTemplate? SelectTemplate(object item, DependencyObject container)
|
|
|
{
|
|
|
- if (item is not CoreTreeNode node) return null;
|
|
|
+ if (item is not CoreTreeNode<TKey> node) return null;
|
|
|
|
|
|
var row = Parent.MapRow(node.Row);
|
|
|
|
|
@@ -1350,7 +1419,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
private object? CalculateSummaryData(IDynamicGridSummary summary, DynamicColumnBase column)
|
|
|
{
|
|
|
var nodes = _tree.View is not null
|
|
|
- ? _tree.View.Nodes.Select(x => x.Item as CoreTreeNode).NotNull()
|
|
|
+ ? _tree.View.Nodes.Select(x => x.Item as CoreTreeNode<TKey>).NotNull()
|
|
|
: Nodes.Nodes;
|
|
|
if(summary is DynamicGridCountSummary count)
|
|
|
{
|
|
@@ -1427,7 +1496,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
#region Refresh
|
|
|
|
|
|
- public CoreTreeNodes Nodes { get; set; }
|
|
|
+ public CoreTreeNodes<TKey> Nodes { get; set; }
|
|
|
|
|
|
private CoreTable? _innerTable;
|
|
|
private bool _invalidating = false;
|
|
@@ -1444,7 +1513,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public void RefreshData(CoreTable data)
|
|
|
{
|
|
|
- var nodes = new CoreTreeNodes();
|
|
|
+ var nodes = new CoreTreeNodes<TKey>(NullKey);
|
|
|
|
|
|
_innerTable = new CoreTable();
|
|
|
_innerTable.LoadColumns(data.Columns);
|
|
@@ -1467,9 +1536,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
ProcessRow(newRow, row);
|
|
|
_innerTable.Rows.Add(newRow);
|
|
|
|
|
|
- var _id = row.Get<Guid>(IDColumn.Property);
|
|
|
- var _parent = row.Get<Guid>(ParentColumn.Property);
|
|
|
- nodes.Add(_id, _parent, newRow);
|
|
|
+ nodes.Add(GetIDKey(row), GetParentKey(row), newRow);
|
|
|
}
|
|
|
nodes.ColumnChanged += Nodes_ColumnChanged;
|
|
|
Nodes = nodes;
|
|
@@ -1498,9 +1565,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
ProcessRow(newRow, row);
|
|
|
_innerTable.Rows.Add(newRow);
|
|
|
|
|
|
- var _id = row.Get<Guid>(IDColumn.Property);
|
|
|
- var _parent = row.Get<Guid>(ParentColumn.Property);
|
|
|
- Nodes.Add(_id, _parent, newRow);
|
|
|
+ Nodes.Add(GetIDKey(row), GetParentKey(row), newRow);
|
|
|
}
|
|
|
CalculateSummaries();
|
|
|
|
|
@@ -1584,7 +1649,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void UpdateRow(CoreRow row, CoreTreeNode dataRow)
|
|
|
+ public void UpdateRow(CoreRow row, CoreTreeNode<TKey> dataRow)
|
|
|
{
|
|
|
foreach(var (key, value) in row)
|
|
|
{
|
|
@@ -1649,9 +1714,9 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public CoreRow Row { get; set; }
|
|
|
|
|
|
- public CoreTreeNode? Node { get; set; }
|
|
|
+ public CoreTreeNode<TKey>? Node { get; set; }
|
|
|
|
|
|
- public DirectEditingObject(T obj, CoreRow row, CoreTreeNode? node)
|
|
|
+ public DirectEditingObject(T obj, CoreRow row, CoreTreeNode<TKey>? node)
|
|
|
{
|
|
|
Object = obj;
|
|
|
Row = row;
|
|
@@ -1690,7 +1755,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
MessageWindow.ShowError($"Error saving {typeof(T)}", e);
|
|
|
}
|
|
|
}
|
|
|
- private void UpdateData(CoreTreeNode node, int columnIndex)
|
|
|
+ private void UpdateData(CoreTreeNode<TKey> node, int columnIndex)
|
|
|
{
|
|
|
if (GetColumn(columnIndex) is DynamicGridColumn gridcol)
|
|
|
{
|
|
@@ -1741,7 +1806,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
bChanged = false;
|
|
|
}
|
|
|
|
|
|
- private void Nodes_ColumnChanged(CoreTreeNode node, string column)
|
|
|
+ private void Nodes_ColumnChanged(CoreTreeNode<TKey> node, string column)
|
|
|
{
|
|
|
if (_invalidating) return;
|
|
|
|
|
@@ -1859,7 +1924,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
private void RowDragDropController_DragStart(object? sender, TreeGridRowDragStartEventArgs e)
|
|
|
{
|
|
|
- var rows = e.DraggingNodes.Select(node => MapRow((node.Item as CoreTreeNode)?.Row)).NotNull().ToArray();
|
|
|
+ var rows = e.DraggingNodes.Select(node => MapRow((node.Item as CoreTreeNode<TKey>)?.Row)).NotNull().ToArray();
|
|
|
Parent.DragStart(sender, rows);
|
|
|
}
|
|
|
|