Browse Source

Tweaks to utility methods; fixing column header styles for dynamic grid; editing interface for column grouping a little. Made DoChanged on DynamicGrid virtual

Kenric Nugteren 1 year ago
parent
commit
59bf6fb07f

+ 11 - 0
InABox.Core/CoreTable/CoreRow.cs

@@ -335,5 +335,16 @@ namespace InABox.Core
         {
             return rows.Select(x => x.ToObject<T>());
         }
+
+        public static T[] ToArray<T>(this IList<CoreRow> rows)
+            where T : BaseObject, new()
+        {
+            var result = new T[rows.Count];
+            for (var i = 0; i < rows.Count; ++i)
+            {
+                result[i] = rows[i].ToObject<T>();
+            }
+            return result;
+        }
     }
 }

+ 9 - 0
InABox.Core/CoreUtils.cs

@@ -2798,6 +2798,15 @@ namespace InABox.Core
             return (trueResult, falseResult);
         }
 
+        /// <summary>
+        /// Get the value in <paramref name="dictionary"/> for the given <paramref name="key"/>, adding a new instance of <typeparamref name="TValue"/>
+        /// if the value was not found.
+        /// </summary>
+        /// <typeparam name="TKey"></typeparam>
+        /// <typeparam name="TValue"></typeparam>
+        /// <param name="dictionary"></param>
+        /// <param name="key"></param>
+        /// <returns></returns>
         public static TValue GetValueOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
             where TValue : new()
         {

+ 2 - 2
inabox.wpf/DynamicGrid/Columns/DynamicTemplateColumn.cs

@@ -6,9 +6,9 @@ namespace InABox.DynamicGrid;
 
 public class DynamicTemplateColumn : DynamicActionColumn
 {
-    public Func<CoreRow, FrameworkElement> Template { get; protected set; }
+    public Func<CoreRow, FrameworkElement?> Template { get; protected set; }
     
-    public DynamicTemplateColumn(Func<CoreRow, FrameworkElement> template)
+    public DynamicTemplateColumn(Func<CoreRow, FrameworkElement?> template)
     {
         Template = template;
         VerticalHeader = false;

+ 34 - 2
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -135,7 +135,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     public delegate void BeforeSelectionEvent(CancelEventArgs cancel);
     public event BeforeSelectionEvent? OnBeforeSelection;
 
-    public void DoChanged() => OnChanged?.Invoke(this, EventArgs.Empty);
+    public virtual void DoChanged() => OnChanged?.Invoke(this, EventArgs.Empty);
 
     public event EditorValueChangedHandler? OnEditorValueChanged;
 
@@ -832,6 +832,10 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
     public DynamicGridColumnGroupings ColumnGroupings { get; set; }
 
+    /// <summary>
+    /// Create a new column header group, and return it for editing.
+    /// </summary>
+    /// <returns></returns>
     public DynamicGridColumnGrouping AddColumnGrouping()
     {
         var group = new DynamicGridColumnGrouping();
@@ -839,6 +843,19 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         return group;
     }
 
+    /// <summary>
+    /// Gets the current column header group, and if there is none, create a new one.
+    /// </summary>
+    /// <returns></returns>
+    public DynamicGridColumnGrouping GetColumnGrouping()
+    {
+        if(ColumnGroupings.Count == 0)
+        {
+            return AddColumnGrouping();
+        }
+        return ColumnGroupings[^1];
+    }
+
     #endregion
 
     protected virtual DynamicGridColumns LoadColumns()
@@ -877,7 +894,6 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         return columns;
     }
 
-
     private bool SwapRows(int row1, int row2)
     {
 
@@ -906,6 +922,19 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     {
         DoCustomiseColumnsEvent(this,columns);
     }
+
+    /// <summary>
+    /// Handle to configure column groups.
+    /// </summary>
+    /// <remarks>
+    /// This is called after <see cref="LoadColumns"/>, so by the time this is called, both <see cref="VisibleColumns"/>
+    /// and <see cref="ActionColumns"/> will be loaded, which means one can reference these in the column groups.
+    /// <br/>
+    /// <b>Note:</b> <see cref="ColumnGroupings"/> is cleared before this function is called.
+    /// </remarks>
+    protected virtual void ConfigureColumnGroups()
+    {
+    }
     
     private void ReloadColumns()
     {
@@ -915,6 +944,9 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
         ConfigureColumns(VisibleColumns /*, true */);
 
+        ColumnGroupings.Clear();
+        ConfigureColumnGroups();
+
         UIComponent.RefreshColumns(VisibleColumns, ActionColumns, ColumnGroupings);
     }
 

+ 33 - 2
inabox.wpf/DynamicGrid/UIComponent/DynamicGridGridUIComponent.cs

@@ -4,6 +4,7 @@ using InABox.WPF;
 using org.omg.PortableInterceptor;
 using Syncfusion.Data;
 using Syncfusion.UI.Xaml.Grid;
+using Syncfusion.UI.Xaml.Grid.Cells;
 using Syncfusion.UI.Xaml.Grid.Helpers;
 using Syncfusion.UI.Xaml.ScrollAxis;
 using Syncfusion.Windows.Shared;
@@ -578,6 +579,29 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
     #region Columns
 
+    private class StackedHeaderRenderer : GridStackedHeaderCellRenderer
+    {
+        private Style Style;
+
+        public StackedHeaderRenderer()
+        {
+            var headstyle = new Style(typeof(GridStackedHeaderCellControl));
+            headstyle.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Gainsboro)));
+            headstyle.Setters.Add(new Setter(Control.ForegroundProperty, new SolidColorBrush(Colors.Black)));
+            headstyle.Setters.Add(new Setter(Control.FontSizeProperty, 12D));
+            headstyle.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0.0, 0.0, 0, 0)));
+            headstyle.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0, 0, 0.75, 0.75)));
+
+            Style = headstyle;
+        }
+
+        public override void OnInitializeEditElement(DataColumnBase dataColumn, GridStackedHeaderCellControl uiElement, object dataContext)
+        {
+            uiElement.Style = Style;
+            base.OnInitializeEditElement(dataColumn, uiElement, dataContext);
+        }
+    }
+
     private void LoadStackedHeaders(DynamicGridColumnGroupings groupings)
     {
         DataGrid.StackedHeaderRows.Clear();
@@ -611,6 +635,12 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
             DataGrid.StackedHeaderRows.Add(row);
         }
+
+        if(groupings.Count > 0)
+        {
+            DataGrid.CellRenderers.Remove("StackedHeader");
+            DataGrid.CellRenderers.Add("StackedHeader", new StackedHeaderRenderer());
+        }
     }
 
     private readonly List<DynamicColumnBase> ColumnList = new();
@@ -653,6 +683,7 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
                 var summary = column.Summary();
                 if (summary != null)
                 {
+                    summary.Name = sColName;
                     summary.MappingName = sColName;
                     Summaries.Add(summary);
                 }
@@ -846,9 +877,9 @@ public class DynamicGridGridUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         }
     }
 
-    public class TemplateColumnSelector(DynamicGridGridUIComponent<T> parent, Func<CoreRow, FrameworkElement> dataTemplate) : DataTemplateSelector
+    public class TemplateColumnSelector(DynamicGridGridUIComponent<T> parent, Func<CoreRow, FrameworkElement?> dataTemplate) : DataTemplateSelector
     {
-        public Func<CoreRow, FrameworkElement> DataTemplate { get; init; } = dataTemplate;
+        public Func<CoreRow, FrameworkElement?> DataTemplate { get; init; } = dataTemplate;
 
         public DynamicGridGridUIComponent<T> Parent { get; init; } = parent;
 

+ 33 - 2
inabox.wpf/DynamicGrid/UIComponent/DynamicGridTreeUIComponent.cs

@@ -21,6 +21,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using Syncfusion.UI.Xaml.TreeGrid.Filtering;
+using Syncfusion.UI.Xaml.TreeGrid.Cells;
 
 namespace InABox.DynamicGrid;
 
@@ -596,6 +597,29 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
     #region Columns
 
+    private class StackedHeaderRenderer : TreeGridStackedHeaderCellRenderer
+    {
+        private Style Style;
+
+        public StackedHeaderRenderer()
+        {
+            var headstyle = new Style(typeof(TreeGridStackedHeaderCell));
+            headstyle.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Gainsboro)));
+            headstyle.Setters.Add(new Setter(Control.ForegroundProperty, new SolidColorBrush(Colors.Black)));
+            headstyle.Setters.Add(new Setter(Control.FontSizeProperty, 12D));
+            headstyle.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0.0, 0.0, 0, 0)));
+            headstyle.Setters.Add(new Setter(Control.MarginProperty, new Thickness(0, 0, 0.75, 0.75)));
+
+            Style = headstyle;
+        }
+
+        public override void OnInitializeEditElement(TreeDataColumnBase dataColumn, TreeGridStackedHeaderCell uiElement, object dataContext)
+        {
+            uiElement.Style = Style;
+            base.OnInitializeEditElement(dataColumn, uiElement, dataContext);
+        }
+    }
+
     private readonly List<DynamicColumnBase> ColumnList = new();
 
     private List<DynamicActionColumn> ActionColumns = new();
@@ -628,9 +652,9 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
         }
     }
 
-    public class TemplateColumnSelector(DynamicGridTreeUIComponent<T> parent, Func<CoreRow, FrameworkElement> dataTemplate) : DataTemplateSelector
+    public class TemplateColumnSelector(DynamicGridTreeUIComponent<T> parent, Func<CoreRow, FrameworkElement?> dataTemplate) : DataTemplateSelector
     {
-        public Func<CoreRow, FrameworkElement> DataTemplate { get; init; } = dataTemplate;
+        public Func<CoreRow, FrameworkElement?> DataTemplate { get; init; } = dataTemplate;
 
         public DynamicGridTreeUIComponent<T> Parent { get; init; } = parent;
 
@@ -679,6 +703,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
                     newcol.Padding = new Thickness(4);
                     newcol.ColumnSizer = TreeColumnSizer.None;
                     newcol.HeaderText = column.HeaderText;
+                    newcol.MappingName = sColName;
 
                     ApplyFilterStyle(newcol, false, true);
 
@@ -783,6 +808,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
                     newcol.AllowSorting = false;
                     newcol.ShowToolTip = false;
                     newcol.ShowHeaderToolTip = false;
+                    newcol.MappingName = sColName;
                     
                     ApplyFilterStyle(newcol, false, true);
 
@@ -906,6 +932,11 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
 
             _tree.StackedHeaderRows.Add(row);
         }
+        if(groupings.Count > 0)
+        {
+            _tree.CellRenderers.Remove("StackedHeader");
+            _tree.CellRenderers.Add("StackedHeader", new StackedHeaderRenderer());
+        }
     }
 
     public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns, DynamicGridColumnGroupings groupings)