Browse Source

Fixed Importing for One-To-Many Grids
DynamicTreegrid now provides selected + recursive children ID values when requested
Removed DataModel dependency for Expression Variables

Frank van den Bos 2 years ago
parent
commit
957e7addcb

+ 7 - 30
InABox.Core/Editors/ButtonEditor.cs

@@ -3,50 +3,27 @@ using System.ComponentModel;
 
 namespace InABox.Core
 {
-    public class ButtonEditorCommandArgs : CancelEventArgs
+    public class ButtonEditorClickArgs : CancelEventArgs
     {
         public String Data { get; set; }
     }
-
-    public delegate ButtonEditorCommand OnCommandCreated();
-    public abstract class ButtonEditorCommand
-    {
-        public abstract void Execute(object sender, ButtonEditorCommandArgs args);
-    }
-
-
+    
     public class ButtonEditor : BaseEditor
     {
-        private Type _commandtype;
-
-        public event OnCommandCreated OnCommandCreate;
+        public Action<object,ButtonEditorClickArgs> OnClick { get; set; }
+        
         public String Label { get; set; }
 
-        public ButtonEditor(Type commandtype)
+        public ButtonEditor()
         {
-            if (!typeof(ButtonEditorCommand).IsAssignableFrom(commandtype))
-                throw new InvalidCastException("Command must be of type ButtonEditorCommand");
-
-            _commandtype = commandtype;
-
-
             Label = "Edit";
             Alignment = Alignment.NotSet;
         }
 
         protected override BaseEditor DoClone()
         {
-            return new ButtonEditor(_commandtype);
-        }
-
-        public ButtonEditorCommand? CreateCommand()
-        {
-            var delegatecommand = OnCommandCreate?.Invoke();
-            if (delegatecommand != null)
-                return delegatecommand;
-
-            var command = Activator.CreateInstance(_commandtype) as ButtonEditorCommand;
-            return command;
+            return new ButtonEditor() { OnClick = this.OnClick };
         }
+        
     }
 }

+ 6 - 3
InABox.Core/Editors/EmbeddedListEditor.cs

@@ -10,20 +10,23 @@ namespace InABox.Core
         public Type DataType;
         
         public String Label { get; set; }
+        
+        public bool DirectEdit { get; set; }
 
         public event EmbeddedListEditorCreateButtons OnCreateButtons;
 
         public void CreateButtons(object sender) => OnCreateButtons?.Invoke(sender);
 
-        public EmbeddedListEditor(Type dataType, String label = "Edit")
+        public EmbeddedListEditor(Type dataType)
         {
             if (!typeof(BaseObject).IsAssignableFrom(dataType))
                 throw new InvalidCastException("DataType must be of type BaseObject");
             DataType = dataType;
-            Label = label;
+            Label = "Edit";
+            DirectEdit = false;
         }
 
-        protected override BaseEditor DoClone() => new EmbeddedListEditor(DataType, Label);
+        protected override BaseEditor DoClone() => new EmbeddedListEditor(DataType) { Label = this.Label, DirectEdit = this.DirectEdit };
         
     }
 }

+ 8 - 21
InABox.Core/Editors/ExpressionEditor.cs

@@ -11,7 +11,8 @@ namespace InABox.Core
         public List<string> GetVariables(object?[] items);
     }
 
-    public delegate DataModel GetVariables();
+    public delegate IEnumerable<String> GetVariables();
+    
     public class ExpressionEditor : BaseEditor
     {
         /// <summary>
@@ -44,13 +45,15 @@ namespace InABox.Core
 
         protected override BaseEditor DoClone()
         {
-            return new ExpressionEditor(ModelType, ModelGenerator)
+            var result = new ExpressionEditor(ModelType, ModelGenerator)
             {
                 VariableNames = VariableNames
             };
+            result.OnGetVariables = OnGetVariables;
+            return result;
         }
 
-        public List<string> GetVariables(object?[] items)
+        public IEnumerable<String> GetVariables(object?[] items)
         {         
             if (VariableNames != null)
                 return VariableNames;
@@ -62,25 +65,9 @@ namespace InABox.Core
             if (ModelType != null)
                 return CoreExpression.GetModelVariables(ModelType);
 
-            var model = OnGetVariables?.Invoke();
-            if (model != null)
-                return GetVariablesFromDataModel(model);
-            return new List<string>();
+            return OnGetVariables?.Invoke() ?? new String[] { };
         }
 
-        private List<string> GetVariablesFromDataModel(DataModel model)
-        {
-            List<string> list = new List<string>();
-            foreach (var table in model.DefaultTables)
-            {
-                foreach (var col in table.Columns)
-                {
-                    if (col.ToString() != "ID")
-                        list.Add(table.ToString() + "." + col.ToString());
-                }
-            }
-            list.Sort();
-            return list;
-        }
+
     }
 }

+ 29 - 12
InABox.Core/Imports/BaseImporter.cs

@@ -55,6 +55,10 @@ namespace InABox.Core
 
         public event ImportPostProcessEvent AfterProcess;
 
+        public event ImportLoadEvent OnLoad;
+
+        public event ImportSaveEvent OnSave;
+
         public int Import()
         {
             _log.Clear();
@@ -75,7 +79,7 @@ namespace InABox.Core
                 {
                     if (keylookup == null)
                     {
-                        keylookup = new ImportLookup(typeof(T), "ID");
+                        keylookup = new ImportLookup(typeof(T), "ID", OnLoad);
                         var others = LookupFactory.DefineColumns(typeof(T));
                         foreach (var other in others.ColumnNames())
                             keylookup.Fields.Add(other);
@@ -99,7 +103,7 @@ namespace InABox.Core
                         var lookup = lookups.FirstOrDefault(x => x.Type == lookuptype);
                         if (lookup == null)
                         {
-                            lookup = new ImportLookup(lookuptype, parentprop + ".ID");
+                            lookup = new ImportLookup(lookuptype, parentprop + ".ID", null);
                             var others = LookupFactory.DefineColumns(lookuptype);
                             foreach (var other in others.ColumnNames())
                                 lookup.Fields.Add(other);
@@ -286,7 +290,10 @@ namespace InABox.Core
                             {
                                 var bNewKey = keylookup != null && item.ID == Guid.Empty;
 
-                                new Client<T>().Save(item, "");
+                                if (OnSave != null)
+                                    OnSave?.Invoke(this, item);
+                                else
+                                    new Client<T>().Save(item, "");
 
                                 if (bNewKey)
                                 {
@@ -326,28 +333,38 @@ namespace InABox.Core
 
         private class ImportLookup
         {
-            public ImportLookup(Type type, string id)
+            public ImportLookup(Type type, string id, ImportLoadEvent onload)
             {
                 Type = type;
                 Fields = new List<string>();
                 ID = id;
+                OnLoad = onload;
             }
 
             public Type Type { get; }
             public List<string> Fields { get; }
             public string ID { get; }
 
+            public event ImportLoadEvent OnLoad;
+            
             public CoreTable Results { get; private set; }
-
+            
             public void Refresh()
             {
-                var client = ClientFactory.CreateClient(Type);
-                var columns = Columns.Create(Type);
-                foreach (var field in Fields)
-                    columns.Add(field);
-                if (!columns.ColumnNames().Contains("ID"))
-                    columns.Add("ID");
-                Results = client.Query(null, columns);
+                if (!Fields.Contains("ID"))
+                    Fields.Add("ID");
+                if (OnLoad != null)
+                    Results = OnLoad?.Invoke(this, Type, Fields.ToArray(), ID);
+                else
+                {
+                    var client = ClientFactory.CreateClient(Type);
+                    var columns = Columns.Create(Type);
+                    foreach (var field in Fields)
+                        columns.Add(field);
+                    if (!columns.ColumnNames().Contains("ID"))
+                        columns.Add("ID");
+                    Results = client.Query(null, columns);
+                }
             }
         }
     }

+ 8 - 1
InABox.Core/Imports/IImporter.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.IO;
 
 namespace InABox.Core
@@ -9,6 +10,10 @@ namespace InABox.Core
 
     public delegate bool ImportPostProcessEvent(object sender, object entity, Dictionary<string, string> values);
 
+    public delegate void ImportSaveEvent(object sender, object entity);
+
+    public delegate CoreTable ImportLoadEvent(object sender, Type type, String[] fields, String ID);
+    
     public interface IImporter
     {
         string[] Properties { get; }
@@ -26,6 +31,8 @@ namespace InABox.Core
 
         event ImportPreProcessEvent BeforeProcess;
         event ImportPostProcessEvent AfterProcess;
+        event ImportSaveEvent OnSave;
+        event ImportLoadEvent OnLoad;
 
         bool Open(Stream stream);
 

+ 2 - 1
InABox.DynamicGrid/BaseDynamicGrid.cs

@@ -61,7 +61,7 @@ namespace InABox.DynamicGrid
         public abstract event OnFilterRecord? OnFilterRecord;
         public event OnCreateItem? OnCreateItem;
         public abstract event OnCustomiseEditor<T>? OnCustomiseEditor;
-        public abstract event OnCustomiseColumns? OnCustomiseColumns;
+        public virtual event OnCustomiseColumns? OnCustomiseColumns;
         public abstract event OnDoubleClick? OnDoubleClick;
 
         public OnGetDynamicGridStyle? OnGetStyle { get; set; }
@@ -99,6 +99,7 @@ namespace InABox.DynamicGrid
 
         public virtual void ConfigureColumns(DynamicGridColumns columns)
         {
+            OnCustomiseColumns?.Invoke(this, columns);
         }
 
         public abstract CoreRow[] SelectedRows { get; set; }

+ 5 - 12
InABox.DynamicGrid/DynamicDataGrid.cs

@@ -532,18 +532,6 @@ namespace InABox.DynamicGrid
             new UserConfiguration<DynamicGridColumns>(tag).Save(columns);
         }
 
-        public override void ConfigureColumns(DynamicGridColumns columns /*, bool dolookups */)
-        {
-            //var eProps = CoreUtils.PropertyList(typeof(Entity), x => true, true);
-            //foreach (String eProp in eProps.Keys)
-            //{
-            //	var column = columns.Where(x => x.ColumnName.Equals(eProp)).FirstOrDefault();
-            //	if (column != null)
-            //		columns.Remove(column);
-            //}
-            base.ConfigureColumns(columns /*, dolookups */);
-        }
-
         protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
         {
             var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == column.ColumnName);
@@ -951,5 +939,10 @@ namespace InABox.DynamicGrid
 
             return columns.Select(x => new Tuple<Type?, CoreTable>(x.Item1, results[x.Item1.Name]));
         }
+
+        protected override CoreTable LoadImportKeys(String[] fields)
+        {
+            return new Client<TEntity>().Query(null, new Columns<TEntity>(fields));
+        }
     }
 }

+ 14 - 4
InABox.DynamicGrid/DynamicEditorGrid.xaml.cs

@@ -212,13 +212,13 @@ namespace InABox.DynamicGrid
                     },
                     ButtonEditor buttonEditor => new ButtonEditorControl()
                     {
-                        Label = buttonEditor.Label,
-                        Command = buttonEditor.CreateCommand()
+                        Label = buttonEditor.Label
                     },
                     EmbeddedListEditor listEditor => new EmbeddedListEditorControl()
                     {
                         DataType = listEditor.DataType,
-                        Label = listEditor.Label
+                        Label = listEditor.Label,
+                        DirectEdit = listEditor.DirectEdit
                     },
                     TimestampEditor => new TimestampEditorControl(),
                     ColorEditor => new ColorEditorControl(),
@@ -534,6 +534,10 @@ namespace InABox.DynamicGrid
                     {
                         ConfigureExpressionEditor(expressionEditorControl);
                     }
+                    else if (Editor is ButtonEditorControl buttonControl && editor is ButtonEditor buttonEditor)
+                    {
+                        ConfigureButtonControl(buttonControl, buttonEditor);
+                    }
 
                     Editor.Configure();
                     if (!Editors.Any(x => x.ColumnName.Equals(Editor.ColumnName)))
@@ -542,6 +546,11 @@ namespace InABox.DynamicGrid
                 }
             }
 
+            private void ConfigureButtonControl(ButtonEditorControl buttonControl, ButtonEditor buttonEditor)
+            {
+                buttonControl.OnClick += buttonEditor.OnClick;
+            }
+
             #endregion
 
             private void EditorValueChanged(IDynamicEditorControl sender, Dictionary<string, object> values)
@@ -792,7 +801,8 @@ namespace InABox.DynamicGrid
         {
             Pages = pages;
 
-            _columns = OnCustomiseColumns?.Invoke(this, null) ?? new DynamicGridColumns();
+            _columns = new DynamicGridColumns();
+            OnCustomiseColumns?.Invoke(this, _columns);
 
             CreateLayout();
             Reload();

+ 13 - 3
InABox.DynamicGrid/DynamicGrid.cs

@@ -2508,10 +2508,11 @@ namespace InABox.DynamicGrid
 
             editor.Setup(items.Any() ? items.First().GetType() : typeof(T), pages, buttons, pageDataHandler, preloadPages);
 
-            editor.OnCustomiseColumns += (o, c) =>
+            editor.OnCustomiseColumns += (sender, columns) =>
             {
-                ConfigureColumns(MasterColumns /*, true */);
-                return MasterColumns;
+                columns.Clear();
+                columns.AddRange(MasterColumns);
+                ConfigureColumns(columns);
             };
 
             editor.OnDefineEditor += (o, c) =>
@@ -2987,6 +2988,13 @@ namespace InABox.DynamicGrid
 
         #region Import / Export
 
+        protected virtual CoreTable LoadImportKeys(String[] fields)
+        {
+            var result = new CoreTable();
+            result.LoadColumns(new Columns<T>(fields));
+            return result;
+        }
+        
         protected virtual Guid GetImportID()
         {
             return Guid.Empty;
@@ -3012,6 +3020,8 @@ namespace InABox.DynamicGrid
             );
             list.OnImportItem += o => { return CustomiseImportItem((T)o); };
             list.OnCustomiseImport += (o, args) => { args.FileName = CustomiseImportFileName(args.FileName); };
+            list.OnSave += (sender, entity) => SaveItem(entity as T);
+            list.OnLoad += (sender, type, fields, id) => LoadImportKeys(fields);
             list.ShowDialog();
             Refresh(false, true);
         }

+ 1 - 1
InABox.DynamicGrid/DynamicGridCommon.cs

@@ -63,7 +63,7 @@ namespace InABox.DynamicGrid
 
     public delegate void OnUnloadPage(IDynamicEditorPage page, bool saved);
 
-    public delegate DynamicGridColumns OnCustomiseColumns(object sender, DynamicGridColumns? source);
+    public delegate void OnCustomiseColumns(object sender, DynamicGridColumns columns);
 
     public delegate BaseEditor? OnGetEditor(DynamicGridColumn column);
 

+ 7 - 1
InABox.DynamicGrid/DynamicImportGrid.cs

@@ -47,6 +47,10 @@ namespace InABox.DynamicGrid
 
         public event OnCustomiseImport OnCustomiseImport;
 
+        public event ImportSaveEvent OnSave;
+
+        public event ImportLoadEvent OnLoad;
+
         protected override void ShowHelp(string slug)
         {
             base.ShowHelp("Import_Data");
@@ -151,7 +155,9 @@ namespace InABox.DynamicGrid
                             return bOK;
                         };
 
-
+                        importer.OnSave += (sender, entity) => OnSave?.Invoke(sender, entity);
+                        importer.OnLoad += (sender, type, fields, id) => OnLoad(sender, type, fields, id); 
+                        
                         importer.OnNotify += (o, m) => { Progress.SetMessage(m); };
 
                         var settings = arg.Get<Importer, string>(c => c.Definition);

+ 8 - 0
InABox.DynamicGrid/DynamicImportList.xaml.cs

@@ -1,6 +1,7 @@
 using InABox.Wpf;
 using System;
 using System.Windows;
+using InABox.Core;
 
 namespace InABox.DynamicGrid
 {
@@ -16,11 +17,18 @@ namespace InABox.DynamicGrid
             Imports.EntityID = entityid;
             Imports.OnImportItem += o => { return OnImportItem != null ? OnImportItem.Invoke(o) : true; };
             Imports.OnCustomiseImport += (o, e) => { OnCustomiseImport?.Invoke(o, e); };
+            Imports.OnSave += (sender, entity) => OnSave?.Invoke(sender, entity);
+            Imports.OnLoad += (sender, type, fields, id) => OnLoad(sender, type, fields, id);
             Imports.Refresh(true, true);
         }
 
         public event OnImportItem OnImportItem;
 
         public event OnCustomiseImport OnCustomiseImport;
+
+        public event ImportSaveEvent OnSave;
+
+        public event ImportLoadEvent OnLoad;
+
     }
 }

+ 17 - 7
InABox.DynamicGrid/DynamicItemsListGrid.cs

@@ -1,30 +1,39 @@
 using InABox.Core;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Syncfusion.Windows.Tools.Controls;
 
 namespace InABox.DynamicGrid
 {
 
-    public interface IDynamicItemsListGrid
+    public interface IDynamicItemsListGrid : IDynamicGrid
     {
-        
+        IEnumerable<object> Items { get; set; }
     }
     
     public class DynamicItemsListGrid<T> : DynamicGrid<T>, IDynamicItemsListGrid
         where T : BaseObject, new()
     {
-        public List<T> Items { get; set; }
+        
+        private List<T> _items = new List<T>();
 
-        public DynamicItemsListGrid() : this(new()) { }
+        public List<T> Items 
+        { 
+            get => _items; 
+            set => _items = value; 
+        }
 
-        public DynamicItemsListGrid(List<T> items) : base()
+        IEnumerable<object> IDynamicItemsListGrid.Items
         {
-            Items = items;
+            get => _items.Cast<object>(); 
+            set => _items = value.OfType<T>().ToList();
         }
-
+        
         protected override void DeleteItems(params CoreRow[] rows)
         {
             foreach (var row in rows.OrderByDescending(x => x.Index))
@@ -54,6 +63,7 @@ namespace InABox.DynamicGrid
                 Items.Add(item);
             }
         }
+
     }
 
 }

+ 21 - 0
InABox.DynamicGrid/DynamicOneToManyGrid.cs

@@ -151,6 +151,26 @@ namespace InABox.DynamicGrid
             new Client<TMany>().Save(Items.Where(x => x.IsChanged()), "Updated by User");
         }
 
+        protected override CoreTable LoadImportKeys(string[] fields)
+        {
+            var result = base.LoadImportKeys(fields);
+            result.LoadRows(MasterList);
+            return result;
+        }
+
+        protected override bool CustomiseImportItem(TMany item)
+        {
+            var result = base.CustomiseImportItem(item);
+            if (result)
+            {
+                var prop = (property.GetValue(item) as IEntityLink)!;
+                prop.ID = Item.ID;
+                prop.Synchronise(Item);
+            }
+
+            return result;
+        }
+
         public Size MinimumSize()
         {
             return new Size(400, 400);
@@ -206,6 +226,7 @@ namespace InABox.DynamicGrid
 
         public override void SaveItem(TMany item)
         {
+            
             if (!Items.Contains(item))
                 Items.Add(item);
 

+ 0 - 19
InABox.DynamicGrid/DynamicSpreadsheet.xaml

@@ -1,19 +0,0 @@
-<Syncfusion:RibbonWindow x:Class="InABox.DynamicGrid.DynamicSpreadsheet"
-        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-        xmlns:local="clr-namespace:InABox.DynamicGrid"
-        xmlns:Syncfusion="http://schemas.syncfusion.com/wpf"
-                         Syncfusion:SkinStorage.VisualStyle="Office2013"
-        mc:Ignorable="d"
-        Title="DynamicSpreadsheet" Height="450" Width="800">
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="0"/>
-            <RowDefinition Height="*"/>
-        </Grid.RowDefinitions>
-        <Syncfusion:SfSpreadsheetRibbon Grid.Row="0" DataContext= "{Binding ElementName=Spreadsheet}"  />
-        <Syncfusion:SfSpreadsheet x:Name="Spreadsheet" Grid.Row="1" FormulaBarVisibility="Collapsed" />
-    </Grid>
-</Syncfusion:RibbonWindow>

+ 0 - 45
InABox.DynamicGrid/DynamicSpreadsheet.xaml.cs

@@ -1,45 +0,0 @@
-using System;
-using System.IO;
-using System.Windows;
-using InABox.Clients;
-using InABox.Core;
-using Syncfusion.Windows.Tools.Controls;
-using Syncfusion.XlsIO;
-
-namespace InABox.DynamicGrid
-{
-    public partial class DynamicSpreadsheet : RibbonWindow
-    {
-        public DynamicSpreadsheet()
-        {
-            InitializeComponent();
-
-
-            var filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "user.xlsx");
-            CreateSpreadsheet(filename);
-            Spreadsheet.Open(filename);
-            
-            //Spreadsheet.Create(1);
-            //Spreadsheet.ActiveSheet = Spreadsheet.Workbook.Worksheets[0];
-            //var table = new Client<User>().Query().ToDataTable();
-            //Spreadsheet.ActiveSheet.ImportDataTable(table,true,1,1);
-            // Spreadsheet.ActiveGrid.InvalidateCells();
-
-        }
-
-        private void CreateSpreadsheet(String filename)
-        {
-            using (ExcelEngine excelEngine = new ExcelEngine())
-            {
-                IApplication application = excelEngine.Excel;
-                application.DefaultVersion = ExcelVersion.Excel2013;
-                IWorkbook workbook = application.Workbooks.Create(1);
-                IWorksheet worksheet = workbook.Worksheets[0];
-                
-                var table = new Client<User>().Query().ToDataTable();
-                worksheet.ImportDataTable(table, true, 1, 1);
-                workbook.SaveAs(filename);
-            }
-        }
-    }
-}

+ 26 - 29
InABox.DynamicGrid/DynamicTreeView.cs

@@ -107,8 +107,17 @@ namespace InABox.DynamicGrid
             return node;
         }
 
+        public void GetChildren(List<Guid> nodes, Guid id)
+        {
+            nodes.Add(id);
+            var children = GetChilden(id);
+            foreach (var child in children)
+                GetChildren(nodes, child.ID);
+        }
+        
         public ObservableCollection<DynamicTreeNode> GetChilden(Guid id)
         {
+            
             return new ObservableCollection<DynamicTreeNode>(_nodes.Where(x => x.Parent.Equals(id) && (x.ID != id)));
         }
 
@@ -210,7 +219,7 @@ namespace InABox.DynamicGrid
 
             _menu = new ContextMenu();
             var additem = new MenuItem() { Header = "Add Child Folder" };
-            additem.Click += (o, e) => { AddItem((_tree.SelectedItem as DynamicTreeNode)!.ID); };
+            additem.Click += (o, e) => { DoAddItem((_tree.SelectedItem as DynamicTreeNode)!.ID, true); };
             _menu.Items.Add(additem);
 
             _tree.ContextMenuOpening += _tree_ContextMenuOpening;
@@ -236,7 +245,7 @@ namespace InABox.DynamicGrid
             _dock.SetValue(Grid.RowProperty, 1);
             _grid.Children.Add(_dock);
 
-            _add = CreateButton(Properties.Resources.add.AsBitmapImage(System.Drawing.Color.White), "", "Add Item", (o) => AddItem(Guid.Empty));
+            _add = CreateButton(Properties.Resources.add.AsBitmapImage(System.Drawing.Color.White), "", "Add Item", (o) => DoAddItem(Guid.Empty, true));
             _add.Margin = new Thickness(0, 2, 2, 0);
             _add.Visibility = Visibility.Collapsed;
             _add.SetValue(DockPanel.DockProperty, Dock.Left);
@@ -268,28 +277,8 @@ namespace InABox.DynamicGrid
         public void AddItem(DynamicTreeNode? parentNode = null, bool edit = true)
         {
             var id = parentNode?.ID ?? Guid.Empty;
-
-            try
-            {
-                T item = DoCreateItem(id);
-                if (edit)
-                {
-                    if (DoEditItem(item))
-                    {
-                        DoSaveItem(item);
-                        Refresh();
-                    }
-                }
-                else
-                {
-                    DoSaveItem(item);
-                    Refresh();
-                }
-            }
-            catch (Exception e)
-            {
-                MessageBox.Show(e.Message);
-            }
+            DoAddItem(id, edit);
+            
         }
 
         #endregion
@@ -307,7 +296,7 @@ namespace InABox.DynamicGrid
             }
             else
             {
-                _menu.AddItem("Add Item", null, (_tree.SelectedItem as DynamicTreeNode)!.ID, AddItem);
+                _menu.AddItem("Add Item", null, (_tree.SelectedItem as DynamicTreeNode)!.ID, (id) => DoAddItem(id,true));
             }
         }
 
@@ -393,13 +382,21 @@ namespace InABox.DynamicGrid
         protected abstract void DoSaveItem(T item);
 
         protected abstract bool DoDeleteItem(Guid id);
-
-        private void AddItem(Guid id)
+        
+        protected virtual void DoAddItem(Guid id, bool edit)
         {
             try
             {
                 T item = DoCreateItem(id);
-                if (DoEditItem(item))
+                if (edit)
+                {
+                    if (DoEditItem(item))
+                    {
+                        DoSaveItem(item);
+                        Refresh();
+                    }
+                }
+                else
                 {
                     DoSaveItem(item);
                     Refresh();
@@ -410,7 +407,7 @@ namespace InABox.DynamicGrid
                 MessageBox.Show(e.Message);
             }
         }
-        
+
         private void EditItem(Button button)
         {
             var node = _tree.SelectedItem as DynamicTreeNode;

+ 6 - 4
InABox.DynamicGrid/Editors/ButtonEditorControl.cs

@@ -1,3 +1,4 @@
+using System;
 using System.ComponentModel;
 using System.Windows;
 using System.Windows.Controls;
@@ -7,6 +8,7 @@ using Syncfusion.XlsIO.Parser.Biff_Records.Charts;
 
 namespace InABox.DynamicGrid
 {
+    
     public class ButtonEditorControl : DynamicEditorControl<string>
     {
         private Button Editor;
@@ -14,8 +16,8 @@ namespace InABox.DynamicGrid
         private string _data = "";
 
         public string? Label { get; set; }
-        
-        public ButtonEditorCommand? Command { get; set; }
+
+        public Action<object,ButtonEditorClickArgs> OnClick { get; set; }
         
         protected override FrameworkElement CreateEditor()
         {
@@ -33,8 +35,8 @@ namespace InABox.DynamicGrid
 
         private void Editor_Click(object sender, RoutedEventArgs e)
         {
-            var args = new ButtonEditorCommandArgs() { Cancel = false, Data = _data };
-            Command?.Execute(this, args);
+            var args = new ButtonEditorClickArgs() { Cancel = false, Data = _data };
+            OnClick?.Invoke(this, args);
             if (!args.Cancel)
                 _data = args.Data;
         }

+ 10 - 5
InABox.DynamicGrid/Editors/EmbeddedListEditorControl.cs

@@ -18,6 +18,8 @@ namespace InABox.DynamicGrid
         
         public Type DataType { get; set; }
         
+        public bool DirectEdit { get; set; }
+
         protected override FrameworkElement CreateEditor()
         {
             Editor = new Button
@@ -38,14 +40,17 @@ namespace InABox.DynamicGrid
             var list = Serialization.Deserialize(listtype, _data) ?? (IList)Activator.CreateInstance(listtype)!;
             var gridtype = DynamicGridUtils.FindDynamicGrid(typeof(DynamicItemsListGrid<>), DataType);
             
-            var grid =(Activator.CreateInstance(gridtype, new object[] { list }) as IDynamicGrid)!;
+            var grid =(Activator.CreateInstance(gridtype) as IDynamicItemsListGrid)!;
+            grid.Items = list as IEnumerable<object>;
             grid.Options
                 .BeginUpdate()
                 .Add(DynamicGridOption.AddRows)
+                .Add(DynamicGridOption.EditRows)
                 .Add(DynamicGridOption.DeleteRows)
-                .Add(DynamicGridOption.DirectEdit)
-                .Add(DynamicGridOption.RecordCount)
-                .EndUpdate();
+                .Add(DynamicGridOption.RecordCount);
+            if (DirectEdit)
+                grid.Options.Add(DynamicGridOption.DirectEdit);
+            grid.Options.EndUpdate();
             grid.Refresh(true, true);
 
             (EditorDefinition as EmbeddedListEditor).CreateButtons(grid);
@@ -53,7 +58,7 @@ namespace InABox.DynamicGrid
             var window = new DynamicContentDialog((FrameworkElement)grid);
             if (window.ShowDialog() == true)
             {
-                _data = Serialization.Serialize(list);
+                _data = Serialization.Serialize(grid.Items);
                 CheckChanged();
             }
 

+ 2 - 2
InABox.DynamicGrid/Editors/ExpressionEditor/ExpressionEditorWindow.xaml.cs

@@ -26,7 +26,7 @@ namespace InABox.DynamicGrid
     {
         public static List<Tuple<string, List<FunctionTemplate>>> FunctionTemplates = new();
 
-        public List<string> Variables { get; private set; }
+        public IEnumerable<string> Variables { get; private set; }
 
         public string Expression
         {
@@ -151,7 +151,7 @@ namespace InABox.DynamicGrid
             }
         }
 
-        public ExpressionEditorWindow(List<string> variables)
+        public ExpressionEditorWindow(IEnumerable<string> variables)
         {
             Variables = variables;
 

+ 3 - 5
InABox.DynamicGrid/EmbeddedDynamicEditorForm.xaml.cs

@@ -350,14 +350,12 @@ namespace InABox.DynamicGrid
             OKButton.IsEnabled = !ReadOnly;
         }
 
-        private DynamicGridColumns Editor_OnCustomiseColumns(object sender, DynamicGridColumns? source)
+        private void Editor_OnCustomiseColumns(object sender, DynamicGridColumns columns)
         {
-            var columns = new DynamicGridColumns();
+            columns.Clear();
             if (_items != null && _items.Any())
                 columns.ExtractColumns(_items.First().GetType());
-            if (OnCustomiseColumns != null)
-                columns = OnCustomiseColumns.Invoke(this, columns);
-            return columns;
+            OnCustomiseColumns?.Invoke(this, columns);
         }
 
         private void Btn_Click(object sender, RoutedEventArgs e)

+ 5 - 5
InABox.Reports/ReportGrid.cs

@@ -112,16 +112,16 @@ public class Report
         private bool ReportGrid_OnEditItem(object sender, object item)
         {
             var editor = new DynamicEditorForm(item.GetType());
-            editor.OnCustomiseColumns += Editor_OnDefineGridColumns;
+            //editor.OnCustomiseColumns += Editor_OnDefineGridColumns;
             editor.Items = new[] { (BaseObject)item };
             var bOK = editor.ShowDialog() == true;
             return bOK;
         }
 
-        private DynamicGridColumns Editor_OnDefineGridColumns(object sender, DynamicGridColumns? master)
-        {
-            return LoadColumns();
-        }
+        // private void Editor_OnDefineGridColumns(object sender, DynamicGridColumns columns)
+        // {
+        //      LoadColumns();
+        // }
 
         private bool ExportClick(CoreRow? row)
         {