Browse Source

Adding column groupings and summaries for action columns

Kenric Nugteren 1 year ago
parent
commit
85045092d0

+ 4 - 0
inabox.wpf/DynamicGrid/Columns/DynamicActionColumn.cs

@@ -4,6 +4,7 @@ using System.Windows.Controls;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using InABox.Core;
+using Syncfusion.UI.Xaml.Grid;
 using Image = System.Windows.Controls.Image;
 using Label = System.Windows.Controls.Label;
 
@@ -19,6 +20,8 @@ namespace InABox.DynamicGrid
         public ActionDelegate? Action { get; set; }
 
         public ActionColumnToolTip? ToolTip { get; set; }
+
+        public Func<GridSummaryColumn?>? GetSummary = null;
         
         public string[]? SelectedFilters { get; set; }
         public string[]? Filters { get; set; } = null;
@@ -65,5 +68,6 @@ namespace InABox.DynamicGrid
 
         public abstract object? Data(CoreRow? row);
 
+        public GridSummaryColumn? Summary() => GetSummary?.Invoke();
     }
 }

+ 15 - 1
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -174,6 +174,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         };
 
         ActionColumns = new DynamicActionColumns();
+        ColumnGroupings = new DynamicGridColumnGroupings();
         
         RowStyleSelector = GetRowStyleSelector();
         RowStyleSelector.GetStyle += (row, style) => GetRowStyle(row, style);
@@ -827,6 +828,19 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
     #region Column Handling
 
+    #region Column Grouping
+
+    public DynamicGridColumnGroupings ColumnGroupings { get; set; }
+
+    public DynamicGridColumnGrouping AddColumnGrouping()
+    {
+        var group = new DynamicGridColumnGrouping();
+        ColumnGroupings.Add(group);
+        return group;
+    }
+
+    #endregion
+
     protected virtual DynamicGridColumns LoadColumns()
     {
         var result = new DynamicGridColumns();
@@ -901,7 +915,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
         ConfigureColumns(VisibleColumns /*, true */);
 
-        UIComponent.RefreshColumns(VisibleColumns, ActionColumns);
+        UIComponent.RefreshColumns(VisibleColumns, ActionColumns, ColumnGroupings);
     }
 
     #endregion

+ 23 - 0
inabox.wpf/DynamicGrid/DynamicGridColumns.cs

@@ -64,4 +64,27 @@ public class DynamicGridColumns<T> : DynamicGridColumns
     {
         return Add<T, TProperty>(member, width, caption, format, alignment);
     }
+}
+
+public class DynamicGridColumnGroup(string header, DynamicColumnBase start, DynamicColumnBase end)
+{
+    public string Header { get; set; } = header;
+
+    public DynamicColumnBase StartColumn { get; set; } = start;
+
+    public DynamicColumnBase EndColumn { get; set; } = end;
+}
+
+public class DynamicGridColumnGrouping
+{
+    public List<DynamicGridColumnGroup> Groups = new();
+
+    public void AddGroup(string header, DynamicColumnBase start, DynamicColumnBase end)
+    {
+        Groups.Add(new(header, start, end));
+    }
+}
+
+public class DynamicGridColumnGroupings : List<DynamicGridColumnGrouping>
+{
 }

+ 52 - 4
inabox.wpf/DynamicGrid/UIComponent/DynamicGridGridUIComponent.cs

@@ -578,6 +578,41 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
     #region Columns
 
+    private void LoadStackedHeaders(DynamicGridColumnGroupings groupings)
+    {
+        DataGrid.StackedHeaderRows.Clear();
+        foreach(var grouping in groupings)
+        {
+            var row = new StackedHeaderRow();
+            var i = 0;
+            foreach(var group in grouping.Groups)
+            {
+                var start = Math.Max(i, ColumnList.IndexOf(group.StartColumn));
+                var end = Math.Max(start, ColumnList.IndexOf(group.EndColumn));
+
+                if(end < start)
+                {
+                    i = end + 1;
+                    continue;
+                }
+
+                var cols = Enumerable.Range(start, end - start + 1).Select(i => DataGrid.Columns[i]).ToArray();
+
+                var stackedColumn = new StackedColumn
+                {
+                    HeaderText = group.Header,
+                    ChildColumns = string.Join(',', cols.Select(x => x.MappingName))
+                };
+
+                row.StackedColumns.Add(stackedColumn);
+
+                i = end + 1;
+            }
+
+            DataGrid.StackedHeaderRows.Add(row);
+        }
+    }
+
     private readonly List<DynamicColumnBase> ColumnList = new();
 
     private List<DynamicActionColumn> ActionColumns = new();
@@ -602,6 +637,8 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         });
     }
 
+    private ObservableCollection<ISummaryColumn> Summaries = new();
+
     private void LoadActionColumns(DynamicActionColumnPosition position)
     {
         for (var i = 0; i < ActionColumns.Count; i++)
@@ -613,6 +650,13 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
                 var sColName = string.Format("ActionColumn{0}", i);
                 gridRowResizingOptions.ExcludeColumns.Add(sColName);
 
+                var summary = column.Summary();
+                if (summary != null)
+                {
+                    summary.MappingName = sColName;
+                    Summaries.Add(summary);
+                }
+
                 if (column is DynamicImageColumn imgcol)
                 {
                     var newcol = new GridImageColumn();
@@ -868,11 +912,8 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         column.FilterRowCellStyle = filterstyle;
     }
 
-
     private void LoadDataColumns(DynamicGridColumns columns)
     {
-        var Summaries = new ObservableCollection<ISummaryColumn>();
-
         foreach (var column in columns)
         {
             if (this.CreateEditorColumn(column, out var newcol, out var prop))
@@ -948,6 +989,10 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
             }
         }
 
+    }
+
+    private void LoadSummaries()
+    {
         if (Summaries.Any())
         {
             DataGrid.CellRenderers.Remove("TableSummary");
@@ -962,7 +1007,7 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         }
     }
 
-    public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns)
+    public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns, DynamicGridColumnGroupings groupings)
     {
         // Yo, please don't remove this.
         // The issue was when we were dynamically adding ActionColumns, and if we had to remove and then re-add them, we were getting massive performance hits
@@ -981,9 +1026,12 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
         ActionColumns = actionColumns.ToList();
 
+        Summaries.Clear();
         LoadActionColumns(DynamicActionColumnPosition.Start);
         LoadDataColumns(columns);
         LoadActionColumns(DynamicActionColumnPosition.End);
+        LoadSummaries();
+        LoadStackedHeaders(groupings);
 
         DataGrid.Columns.Resume();
         DataGrid.RefreshColumns();

+ 37 - 1
inabox.wpf/DynamicGrid/UIComponent/DynamicGridTreeUIComponent.cs

@@ -873,7 +873,42 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         }
     }
 
-    public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns)
+    private void LoadStackedHeaders(DynamicGridColumnGroupings groupings)
+    {
+        _tree.StackedHeaderRows.Clear();
+        foreach(var grouping in groupings)
+        {
+            var row = new StackedHeaderRow();
+            var i = 0;
+            foreach(var group in grouping.Groups)
+            {
+                var start = Math.Max(i, ColumnList.IndexOf(group.StartColumn));
+                var end = Math.Max(start, ColumnList.IndexOf(group.EndColumn));
+
+                if(end < start)
+                {
+                    i = end + 1;
+                    continue;
+                }
+
+                var cols = Enumerable.Range(start, end - start + 1).Select(i => _tree.Columns[i]).ToArray();
+
+                var stackedColumn = new StackedColumn
+                {
+                    HeaderText = group.Header,
+                    ChildColumns = string.Join(',', cols.Select(x => x.MappingName))
+                };
+
+                row.StackedColumns.Add(stackedColumn);
+
+                i = end + 1;
+            }
+
+            _tree.StackedHeaderRows.Add(row);
+        }
+    }
+
+    public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns, DynamicGridColumnGroupings groupings)
     {
         _tree.ItemsSource = null;
         _tree.Columns.Suspend();
@@ -894,6 +929,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         LoadActionColumns(DynamicActionColumnPosition.Start);
         LoadDataColumns(columns);
         LoadActionColumns(DynamicActionColumnPosition.End);
+        LoadStackedHeaders(groupings);
 
         _tree.Columns.Resume();
         _tree.RefreshColumns();

+ 1 - 1
inabox.wpf/DynamicGrid/UIComponent/IDynamicGridUIComponent.cs

@@ -72,7 +72,7 @@ public interface IDynamicGridUIComponent<T>
     List<Tuple<string, Func<CoreRow, bool>>> GetFilterPredicates();
 
     void BeforeRefresh();
-    void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns);
+    void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns, DynamicGridColumnGroupings groupings);
     void RefreshData(CoreTable data);
     void InvalidateRow(CoreRow row);