Browse Source

Merge remote-tracking branch 'origin/kenric' into frank

frogsoftware 2 years ago
parent
commit
bc2406da5c

+ 21 - 0
InABox.Core/Client/BaseClient.cs

@@ -286,6 +286,27 @@ namespace InABox.Clients
 
         protected abstract Dictionary<string, CoreTable> DoQueryMultiple(Dictionary<string, IQueryDef> queries);
 
+        public void QueryMultiple(Action<Dictionary<string, CoreTable>?, Exception?> callback, Dictionary<string, IQueryDef> queries)
+        {
+            Task.Run(() =>
+            {
+                Exception? err = null;
+                Dictionary<string, CoreTable>? result = null;
+                try
+                {
+                    result = DoQueryMultiple(queries);
+                }
+                catch (Exception e)
+                {
+                    err = e;
+                }
+                finally
+                {
+                    callback.Invoke(result, err);
+                }
+            });
+        }
+
         #endregion
 
         #region 2FA

+ 38 - 17
InABox.Core/Client/Client.cs

@@ -57,14 +57,18 @@ namespace InABox.Clients
             }
         }
 
-        public static QueryMultipleResults QueryMultiple(params IKeyedQueryDef[] queries)
+        public static void QueryMultiple(
+            Action<Dictionary<string, CoreTable>?, Exception?> callback,
+            Dictionary<string, IQueryDef> queries)
         {
             try
             {
                 using var timer = new Profiler(false);
-                var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
-                timer.Log(result.Sum(x => x.Value.Rows.Count));
-                return new QueryMultipleResults(result);
+                CheckClient().QueryMultiple((result, e) =>
+                {
+                    timer.Dispose(result != null ? result.Sum(x => x.Value.Rows.Count) : -1);
+                    callback?.Invoke(result, e);
+                }, queries);
             }
             catch (RequestException e)
             {
@@ -72,21 +76,38 @@ namespace InABox.Clients
                 throw;
             }
         }
-        public static QueryMultipleResults QueryMultiple(IEnumerable<IKeyedQueryDef> queries)
-        {
-            try
+
+        public static QueryMultipleResults QueryMultiple(params IKeyedQueryDef[] queries) =>
+            new QueryMultipleResults(QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef)));
+
+        public static void QueryMultiple(Action<QueryMultipleResults?, Exception?> callback, params IKeyedQueryDef[] queries) =>
+            QueryMultiple((results, e) =>
             {
-                using var timer = new Profiler(false);
-                var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
-                timer.Log(result.Sum(x => x.Value.Rows.Count));
-                return new QueryMultipleResults(result);
-            }
-            catch (RequestException e)
+                if (results != null)
+                {
+                    callback?.Invoke(new QueryMultipleResults(results), e);
+                }
+                else
+                {
+                    callback?.Invoke(null, e);
+                }
+            }, queries.ToDictionary(x => x.Key, x => x as IQueryDef));
+
+        public static QueryMultipleResults QueryMultiple(IEnumerable<IKeyedQueryDef> queries) =>
+            new QueryMultipleResults(QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef)));
+
+        public static void QueryMultiple(Action<QueryMultipleResults?, Exception?> callback, IEnumerable<IKeyedQueryDef> queries) =>
+            QueryMultiple((results, e) =>
             {
-                ClientFactory.RaiseRequestError(e);
-                throw;
-            }
-        }
+                if(results != null)
+                {
+                    callback?.Invoke(new QueryMultipleResults(results), e);
+                }
+                else
+                {
+                    callback?.Invoke(null, e);
+                }
+            }, queries.ToDictionary(x => x.Key, x => x as IQueryDef));
 
         public static IValidationData Validate(Guid session)
         {

+ 1 - 0
InABox.Core/Client/IClient.cs

@@ -20,6 +20,7 @@ namespace InABox.Clients
         void Delete(object entity, string auditnote);
         void Delete(IList<object> entities, string auditnote);
         Dictionary<string, CoreTable> QueryMultiple(Dictionary<string, IQueryDef> queries);
+        void QueryMultiple(Action<Dictionary<string, CoreTable>?, Exception?> callback, Dictionary<string, IQueryDef> queries);
 
         bool Check2FA(string code, Guid? session = null);
 

+ 5 - 0
InABox.Core/Editors/Utils/ILookupEditor.cs

@@ -12,4 +12,9 @@ namespace InABox.Core
 
         void Clear();
     }
+
+    public static class LookupEditorExtensions
+    {
+        public static bool IsEnumEditor(this ILookupEditor editor) => editor is EnumLookupEditor;
+    }
 }

+ 3 - 5
InABox.Core/Entity.cs

@@ -224,11 +224,9 @@ namespace InABox.Core
 
         private void CheckSequence()
         {
-            if (this is ISequenceable)
+            if (this is ISequenceable seq && seq.Sequence <= 0)
             {
-                var seq = (ISequenceable)this;
-                if (seq.Sequence <= 0)
-                    seq.Sequence = CoreUtils.GenerateSequence();
+                seq.Sequence = CoreUtils.GenerateSequence();
             }
         }
 
@@ -289,7 +287,7 @@ namespace InABox.Core
         }
 
 
-        protected override void DoPropertyChanged(string name, object before, object after)
+        protected override void DoPropertyChanged(string name, object? before, object? after)
         {
             if (!IsObserving())
                 return;

+ 3 - 3
InABox.Core/Filter.cs

@@ -293,7 +293,7 @@ namespace InABox.Core
         IFilter EndsWith(string value);
 
         IFilter InQuery<U>(SubQuery<U> value);
-        IFilter InQuery<U>(Filter<U> filter, Expression<Func<U, object?>> column);
+        IFilter InQuery<U>(Filter<U>? filter, Expression<Func<U, object?>> column);
 
         IFilter All();
         IFilter None();
@@ -891,8 +891,8 @@ namespace InABox.Core
         public Filter<T> InQuery<U>(SubQuery<U> value) => ApplyObjectOperator(Operator.InQuery, value);
         IFilter IFilter.InQuery<U>(SubQuery<U> value) => InQuery(value);
 
-        public Filter<T> InQuery<U>(Filter<U> filter, Expression<Func<U, object?>> column) => InQuery(new SubQuery<U>(filter, new Column<U>(column)));
-        IFilter IFilter.InQuery<U>(Filter<U> value, Expression<Func<U, object?>> column) => InQuery(value, column);
+        public Filter<T> InQuery<U>(Filter<U>? filter, Expression<Func<U, object?>> column) => InQuery(new SubQuery<U>(filter, new Column<U>(column)));
+        IFilter IFilter.InQuery<U>(Filter<U>? filter, Expression<Func<U, object?>> column) => InQuery(filter, column);
 
         #endregion
 

+ 1 - 1
inabox.wpf/DigitalForms/Designer/DynamicFormControlGrid.cs

@@ -19,7 +19,7 @@ namespace InABox.DynamicGrid
 
         protected override void DoReconfigure(FluentList<DynamicGridOption> options)
         {
-            options.AddRange(DynamicGridOption.RecordCount);
+            options.Add(DynamicGridOption.RecordCount);
         }
 
         public List<T> Items { get; set; }

+ 10 - 7
inabox.wpf/DynamicGrid/BaseDynamicGrid.cs

@@ -10,6 +10,7 @@ using System.Windows.Media.Imaging;
 using FastReport.Editor;
 using InABox.Core;
 using Syncfusion.Data;
+using static InABox.DynamicGrid.IDynamicGrid;
 using Selection = InABox.Core.Selection;
 
 namespace InABox.DynamicGrid
@@ -86,9 +87,6 @@ namespace InABox.DynamicGrid
         {
             Options = new FluentList<DynamicGridOption>();
             Options.OnChanged += OptionsChanged;
-
-            DefaultOptions = new FluentList<DynamicGridOption>();
-            DefaultOptions.OnChanged += DefaultOptions_OnChanged;
             
             RowStyleSelector = GetRowStyleSelector();
             RowStyleSelector.GetStyle += (row, style) => GetRowStyle(row, style);
@@ -110,9 +108,9 @@ namespace InABox.DynamicGrid
         /// <summary>
         /// Configure custom buttons and options.
         /// </summary>
-        protected void Reconfigure(FluentList<DynamicGridOption> options)
+        private void Reconfigure(FluentList<DynamicGridOption> options)
         {
-            options.BeginUpdate().Clear().AddRange(DefaultOptions);
+            options.BeginUpdate().Clear();
             DoReconfigure(options);
             OnReconfigure?.Invoke(options);
             options.EndUpdate();
@@ -121,6 +119,12 @@ namespace InABox.DynamicGrid
         {
             Reconfigure(Options);
         }
+        public void Reconfigure(ReconfigureEvent onReconfigure)
+        {
+            OnReconfigure += onReconfigure;
+            Reconfigure();
+        }
+        public bool HasOption(DynamicGridOption option) => Options.Contains(option);
 
         public List<Expression<Func<T, object?>>> HiddenColumns { get; }
 
@@ -136,8 +140,7 @@ namespace InABox.DynamicGrid
 
         //public abstract bool DirectEdit(CoreTable data);
 
-        protected FluentList<DynamicGridOption> Options { get; }
-        public FluentList<DynamicGridOption> DefaultOptions { get; }
+        private FluentList<DynamicGridOption> Options { get; }
 
         public DynamicGridColumns MasterColumns { get; protected set; }
         public DynamicGridColumns VisibleColumns { get; protected set; }

+ 8 - 0
inabox.wpf/DynamicGrid/DynamicColumnGrid.cs

@@ -46,6 +46,14 @@ namespace InABox.DynamicGrid
         //	return LoadColumns();
         //}
 
+        protected override void DoValidate(DynamicGridColumn[] items, List<string> errors)
+        {
+            base.DoValidate(items, errors);
+
+            if (items.Any(x => string.IsNullOrWhiteSpace(x.ColumnName)))
+                errors.Add("[ColumnName] must not be blank!");
+        }
+
         protected override DynamicGridColumns LoadColumns()
         {
             var columns = new DynamicGridColumns

+ 4 - 4
inabox.wpf/DynamicGrid/DynamicDataGrid.cs

@@ -153,13 +153,13 @@ namespace InABox.DynamicGrid
             base.OptionsChanged(sender, args);
             if (MergeBtn != null)
                 MergeBtn.Visibility = Visibility.Collapsed;
-            ShowFilterList = Options.Contains(DynamicGridOption.FilterRows);
+            ShowFilterList = HasOption(DynamicGridOption.FilterRows);
         }
 
         protected override void SelectItems(CoreRow[]? rows)
         {
             base.SelectItems(rows);
-            MergeBtn.Visibility = Options.Contains(DynamicGridOption.MultiSelect) && typeof(TEntity).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge<TEntity>() && rows != null && rows.Length > 1
+            MergeBtn.Visibility = HasOption(DynamicGridOption.MultiSelect) && typeof(TEntity).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge<TEntity>() && rows != null && rows.Length > 1
                 ? Visibility.Visible
                 : Visibility.Collapsed;
         }
@@ -284,7 +284,7 @@ namespace InABox.DynamicGrid
         {
             Filter<TEntity>? filter = null;
             var results = new List<TEntity>();
-            for (var i = 0; i < rows.Length; i = i + ChunkSize)
+            for (var i = 0; i < rows.Length; i += ChunkSize)
             {
                 var chunk = rows.Skip(i).Take(ChunkSize);
                 foreach (var row in chunk)
@@ -497,7 +497,7 @@ namespace InABox.DynamicGrid
 
         protected virtual void GenerateColumns(DynamicGridColumns columns)
         {
-            var cols = new Columns<TEntity>().Default(Options.Contains(DynamicGridOption.DirectEdit)
+            var cols = new Columns<TEntity>().Default(HasOption(DynamicGridOption.DirectEdit)
                 ? new[] { ColumnType.IncludeForeignKeys, ColumnType.ExcludeID }
                 : new ColumnType[] {
                     ColumnType.IncludeLinked, ColumnType.IncludeNestedLinks, ColumnType.IncludeFormulae,

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

@@ -55,7 +55,7 @@ namespace InABox.DynamicGrid
         {
             base.DoReconfigure(options);
 
-            Options.Add(DynamicGridOption.DragTarget);
+            options.Add(DynamicGridOption.DragTarget);
         }
 
         private bool SaveDocument(CoreRow? row)

+ 62 - 51
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -754,31 +754,31 @@ namespace InABox.DynamicGrid
         {
             var reloadColumns = false;
 
-            ColumnsMenu.Visibility = Options.Contains(DynamicGridOption.SelectColumns) ? Visibility.Visible : Visibility.Hidden;
-            Help.Visibility = Options.Contains(DynamicGridOption.ShowHelp) ? Visibility.Visible : Visibility.Collapsed;
+            ColumnsMenu.Visibility = HasOption(DynamicGridOption.SelectColumns) ? Visibility.Visible : Visibility.Hidden;
+            Help.Visibility = HasOption(DynamicGridOption.ShowHelp) ? Visibility.Visible : Visibility.Collapsed;
 
-            Add.Visibility = Options.Contains(DynamicGridOption.AddRows) ? Visibility.Visible : Visibility.Collapsed;
-            Edit.Visibility = Options.Contains(DynamicGridOption.EditRows) ? Visibility.Visible : Visibility.Collapsed;
+            Add.Visibility = HasOption(DynamicGridOption.AddRows) ? Visibility.Visible : Visibility.Collapsed;
+            Edit.Visibility = HasOption(DynamicGridOption.EditRows) ? Visibility.Visible : Visibility.Collapsed;
 
-            EditSpacer.Visibility = Options.Contains(DynamicGridOption.AddRows) || Options.Contains(DynamicGridOption.EditRows)
+            EditSpacer.Visibility = HasOption(DynamicGridOption.AddRows) || HasOption(DynamicGridOption.EditRows)
                 ? Visibility.Visible
                 : Visibility.Collapsed;
 
-            Print.Visibility = Options.Contains(DynamicGridOption.Print) ? Visibility.Visible : Visibility.Collapsed;
-            PrintSpacer.Visibility = Options.Contains(DynamicGridOption.Print) ? Visibility.Visible : Visibility.Collapsed;
+            Print.Visibility = HasOption(DynamicGridOption.Print) ? Visibility.Visible : Visibility.Collapsed;
+            PrintSpacer.Visibility = HasOption(DynamicGridOption.Print) ? Visibility.Visible : Visibility.Collapsed;
 
             Cut.Visibility = IsSequenced ? Visibility.Visible : Visibility.Collapsed;
             Copy.Visibility = IsSequenced ? Visibility.Visible : Visibility.Collapsed;
             Paste.Visibility = IsSequenced ? Visibility.Visible : Visibility.Collapsed;
             ClipboardSpacer.Visibility = IsSequenced ? Visibility.Visible : Visibility.Collapsed;
 
-            Export.Visibility = Options.Contains(DynamicGridOption.ExportData) ? Visibility.Visible : Visibility.Collapsed;
-            Import.Visibility = Options.Contains(DynamicGridOption.ImportData) ? Visibility.Visible : Visibility.Collapsed;
-            ExportSpacer.Visibility = Options.Contains(DynamicGridOption.ExportData) || Options.Contains(DynamicGridOption.ImportData)
+            Export.Visibility = HasOption(DynamicGridOption.ExportData) ? Visibility.Visible : Visibility.Collapsed;
+            Import.Visibility = HasOption(DynamicGridOption.ImportData) ? Visibility.Visible : Visibility.Collapsed;
+            ExportSpacer.Visibility = HasOption(DynamicGridOption.ExportData) || HasOption(DynamicGridOption.ImportData)
                 ? Visibility.Visible
                 : Visibility.Collapsed;
 
-            var allowEditing = Options.Contains(DynamicGridOption.DirectEdit);
+            var allowEditing = HasOption(DynamicGridOption.DirectEdit);
             if (DataGrid.AllowEditing != allowEditing)
             {
                 DataGrid.NavigationMode = allowEditing ? NavigationMode.Cell : NavigationMode.Row;
@@ -786,13 +786,13 @@ namespace InABox.DynamicGrid
                 reloadColumns = true;
             }
 
-            Count.Visibility = Options.Contains(DynamicGridOption.RecordCount) ? Visibility.Visible : Visibility.Collapsed;
+            Count.Visibility = HasOption(DynamicGridOption.RecordCount) ? Visibility.Visible : Visibility.Collapsed;
 
-            Delete.Visibility = Options.Contains(DynamicGridOption.DeleteRows) ? Visibility.Visible : Visibility.Collapsed;
-            DataGrid.AllowFiltering = Options.Contains(DynamicGridOption.FilterRows);
-            DataGrid.FilterRowPosition = Options.Contains(DynamicGridOption.FilterRows) ? FilterRowPosition.FixedTop : FilterRowPosition.None;
+            Delete.Visibility = HasOption(DynamicGridOption.DeleteRows) ? Visibility.Visible : Visibility.Collapsed;
+            DataGrid.AllowFiltering = HasOption(DynamicGridOption.FilterRows);
+            DataGrid.FilterRowPosition = HasOption(DynamicGridOption.FilterRows) ? FilterRowPosition.FixedTop : FilterRowPosition.None;
 
-            if (Options.Contains(DynamicGridOption.DragSource))
+            if (HasOption(DynamicGridOption.DragSource))
             {
                 if (!DataGrid.AllowDraggingRows)
                 {
@@ -809,13 +809,13 @@ namespace InABox.DynamicGrid
                 }
             }
             
-            DataGrid.AllowDrop = Options.Contains(DynamicGridOption.DragTarget);
+            DataGrid.AllowDrop = HasOption(DynamicGridOption.DragTarget);
             
-            DataGrid.SelectionMode = Options.Contains(DynamicGridOption.MultiSelect) ? GridSelectionMode.Extended : GridSelectionMode.Single;
+            DataGrid.SelectionMode = HasOption(DynamicGridOption.MultiSelect) ? GridSelectionMode.Extended : GridSelectionMode.Single;
             if (up != null)
-                up.Position = Options.Contains(DynamicGridOption.EditRows) ? DynamicActionColumnPosition.Start : DynamicActionColumnPosition.Hidden;
+                up.Position = HasOption(DynamicGridOption.EditRows) ? DynamicActionColumnPosition.Start : DynamicActionColumnPosition.Hidden;
             if (down != null)
-                down.Position = Options.Contains(DynamicGridOption.EditRows) ? DynamicActionColumnPosition.Start : DynamicActionColumnPosition.Hidden;
+                down.Position = HasOption(DynamicGridOption.EditRows) ? DynamicActionColumnPosition.Start : DynamicActionColumnPosition.Hidden;
 
             if (DuplicateBtn != null)
                 DuplicateBtn.Visibility = Visibility.Collapsed;
@@ -855,7 +855,7 @@ namespace InABox.DynamicGrid
 
         private void DataGrid_CurrentCellActivated(object? sender, CurrentCellActivatedEventArgs e)
         {
-            if (!Options.Contains(DynamicGridOption.DirectEdit))
+            if (!HasOption(DynamicGridOption.DirectEdit))
                 return;
             if ((DataGrid.SelectionController.CurrentCellManager.CurrentCell?.IsEditing != true) && e.ActivationTrigger == ActivationTrigger.Keyboard)
                 DataGrid.SelectionController.CurrentCellManager.BeginEdit();
@@ -924,7 +924,7 @@ namespace InABox.DynamicGrid
 
         private CoreRow? GetRowFromIndex(int rowIndex)
         {
-            var row = rowIndex - (Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1);
+            var row = rowIndex - (HasOption(DynamicGridOption.FilterRows) ? 2 : 1);
             if (row < 0 || DataGridItems is null)
                 return null;
             row = DataGridItems.Rows.IndexOf((DataGrid.View.Records[row].Data as DataRowView)!.Row);
@@ -992,7 +992,7 @@ namespace InABox.DynamicGrid
 
         private void DataGrid_CurrentCellBeginEdit(object? sender, CurrentCellBeginEditEventArgs e)
         {
-            var headerrows = Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1;
+            var headerrows = HasOption(DynamicGridOption.FilterRows) ? 2 : 1;
             if (e.RowColumnIndex.RowIndex < headerrows || DataGridItems is null)
                 return;
 
@@ -1022,7 +1022,7 @@ namespace InABox.DynamicGrid
 
         private void DataGrid_CurrentCellValueChanged(object? sender, CurrentCellValueChangedEventArgs e)
         {
-            var headerrows = Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1;
+            var headerrows = HasOption(DynamicGridOption.FilterRows) ? 2 : 1;
             if (e.RowColumnIndex.RowIndex < headerrows)
                 return;
             if (e.Column is GridCheckBoxColumn)
@@ -1037,7 +1037,7 @@ namespace InABox.DynamicGrid
 
         private void DataGrid_CurrentCellDropDownSelectionChanged(object? sender, CurrentCellDropDownSelectionChangedEventArgs e)
         {
-            var headerrows = Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1;
+            var headerrows = HasOption(DynamicGridOption.FilterRows) ? 2 : 1;
             if (e.RowColumnIndex.RowIndex < headerrows)
                 return;
             inplaceeditor ??= LoadItem(Data.Rows[e.RowColumnIndex.RowIndex - headerrows]);
@@ -1062,7 +1062,7 @@ namespace InABox.DynamicGrid
 
         private void DataGrid_CurrentCellEndEdit(object? sender, CurrentCellEndEditEventArgs e)
         {
-            var headerrows = Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1;
+            var headerrows = HasOption(DynamicGridOption.FilterRows) ? 2 : 1;
             if (e.RowColumnIndex.RowIndex < headerrows)
                 return;
             if (inplaceeditor is not null && bChanged) 
@@ -1081,7 +1081,7 @@ namespace InABox.DynamicGrid
                 return;
             var table = DataGridItems;
             
-            var iRow = SelectedRows.First().Index; //e.RowColumnIndex.RowIndex - (Options.Contains(DynamicGridOptions.FilterRows) ? 2 : 1);
+            var iRow = SelectedRows.First().Index; //e.RowColumnIndex.RowIndex - (HasOption(DynamicGridOptions.FilterRows) ? 2 : 1);
             if (table is null || iRow > table.Rows.Count)
                 return;
             var row = table.Rows[iRow];
@@ -1223,8 +1223,8 @@ namespace InABox.DynamicGrid
             foreach (var row in rows.Where(x => x.Index > -1))
             {
                 //DataTable table = (DataTable)DataGrid.ItemsSource;
-                if (bFirst || Options.Contains(DynamicGridOption.MultiSelect))
-                    DataGrid.SelectedItems.Add(DataGrid.GetRecordAtRowIndex(row.Index + (Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1)));
+                if (bFirst || HasOption(DynamicGridOption.MultiSelect))
+                    DataGrid.SelectedItems.Add(DataGrid.GetRecordAtRowIndex(row.Index + (HasOption(DynamicGridOption.FilterRows) ? 2 : 1)));
                 bFirst = false;
             }
         }
@@ -1326,8 +1326,8 @@ namespace InABox.DynamicGrid
             if ((columnindex < 0) || (columnindex >= ColumnList.Count))
                 return;
             var column = ColumnList[columnindex] as DynamicActionColumn;
-            var rowindex = rowcolumnindex.RowIndex - (Options.Contains(DynamicGridOption.FilterRows) ? 2 : 1);
-            if (rowindex < 0)
+            var rowindex = rowcolumnindex.RowIndex - (HasOption(DynamicGridOption.FilterRows) ? 2 : 1);
+            if (rowindex < 0 || rowindex >= Data.Rows.Count)
                 return;
             var row = Data.Rows[rowindex];
             var menu = column?.ContextMenu?.Invoke(SelectedRows);
@@ -1393,7 +1393,7 @@ namespace InABox.DynamicGrid
 
         protected virtual void DoDoubleClick(object sender)
         {
-            if (Options.Contains(DynamicGridOption.DirectEdit))
+            if (HasOption(DynamicGridOption.DirectEdit))
                 return;
 
             SelectItems(SelectedRows);
@@ -1401,7 +1401,7 @@ namespace InABox.DynamicGrid
             OnDoubleClick?.Invoke(sender, args);
             if (args.Handled)
                 return;
-            if (Options.Contains(DynamicGridOption.EditRows))
+            if (HasOption(DynamicGridOption.EditRows))
                 DoEdit();
         }
 
@@ -1432,7 +1432,7 @@ namespace InABox.DynamicGrid
         {
             var result = new DynamicGridColumns();
 
-            var cols = Options.Contains(DynamicGridOption.DirectEdit)
+            var cols = HasOption(DynamicGridOption.DirectEdit)
                 ? new Columns<T>().Default(ColumnType.IncludeForeignKeys, ColumnType.ExcludeID)
                 : new Columns<T>().Default(ColumnType.IncludeLinked, ColumnType.ExcludeID);
             result.AddRange(MasterColumns.Where(x => cols.Items.Any(c => c.Property.Equals(x.ColumnName)))
@@ -1834,7 +1834,7 @@ namespace InABox.DynamicGrid
                     }
                     else if (prop.PropertyType == typeof(bool))
                     {
-                        if (Options.Contains(DynamicGridOption.DirectEdit))
+                        if (HasOption(DynamicGridOption.DirectEdit))
                         {
                             var checkcol = new GridCheckBoxColumn
                             {
@@ -1916,7 +1916,7 @@ namespace InABox.DynamicGrid
                             () =>
                             {
                                 var result = new DockPanel();
-                                if (Options.Contains(DynamicGridOption.DirectEdit))
+                                if (HasOption(DynamicGridOption.DirectEdit))
                                 {
                                     var button = new Button();
                                     button.Content = "..";
@@ -1992,10 +1992,21 @@ namespace InABox.DynamicGrid
                         //lookupcol.DisplayMemberPath = "Value";
                         //lookupcol.ItemsSource = lookups;
 
-                        var table = lookupEditor.Values(column.ColumnName).ToDataTable();
-                        lookupcol.SelectedValuePath = table.Columns[0].ColumnName;
-                        lookupcol.DisplayMemberPath = "Display";
-                        lookupcol.ItemsSource = table.DefaultView;
+                        var data = lookupEditor.Values(column.ColumnName);
+
+                        var items = new List<Tuple<object?, string>>();
+                        if (!lookupEditor.IsEnumEditor())
+                        {
+                            items.Add(new(null, ""));
+                        }
+                        foreach(var row in data.Rows)
+                        {
+                            items.Add(new(row[data.Columns[0].ColumnName], (row["Display"] ?? "").ToString() ?? ""));
+                        }
+
+                        lookupcol.SelectedValuePath = "Item1";
+                        lookupcol.DisplayMemberPath = "Item2";
+                        lookupcol.ItemsSource = items;
                         newcol = lookupcol;
                     }
                     else
@@ -2007,7 +2018,7 @@ namespace InABox.DynamicGrid
                         newcol = textcol;
                         if (prop.PropertyType == typeof(string[]))
                             newcol.DisplayBinding = new Binding { Path = new PropertyPath(scolname), Converter = new StringArrayConverter() };
-                        textcol.AllowEditing = Options.Contains(DynamicGridOption.DirectEdit);
+                        textcol.AllowEditing = HasOption(DynamicGridOption.DirectEdit);
                         textcol.UpdateTrigger = UpdateSourceTrigger.PropertyChanged;
                     }
 
@@ -2046,7 +2057,7 @@ namespace InABox.DynamicGrid
                     newcol.HeaderStyle = headstyle;
 
                     var cellstyle = new Style();
-                    if (Options.Contains(DynamicGridOption.DirectEdit))
+                    if (HasOption(DynamicGridOption.DirectEdit))
                     {
                         if (prop.Editor is null || !prop.Editor.Editable.IsDirectEditable())
                         {
@@ -2417,7 +2428,7 @@ namespace InABox.DynamicGrid
                 if (!result.Columns.Contains(colname))
                 {
                     result.Columns.Add(colname, column.DataType);
-                    if (!Options.Contains(DynamicGridOption.DirectEdit))
+                    if (!HasOption(DynamicGridOption.DirectEdit))
                         defaults.Add(column.DataType.GetDefault());
                 }
             }
@@ -2456,7 +2467,7 @@ namespace InABox.DynamicGrid
         {
             var count = DataGrid.View != null ? DataGrid.View.Records.Count : Data.Rows.Count;
             Count.Content = string.Format("{0} Records", count);
-            //Count.Visibility = _Options.Contains(DynamicGridOptions.RecordCount) && (count > 0) ? Visibility.Visible : Visibility.Collapsed;
+            //Count.Visibility = _HasOption(DynamicGridOptions.RecordCount) && (count > 0) ? Visibility.Visible : Visibility.Collapsed;
         }
 
         public IList<CoreRow> FilteredRows()
@@ -2728,7 +2739,7 @@ namespace InABox.DynamicGrid
         {
             //CoreRow row = (SelectedRow > -1) && (SelectedRow < Data.Rows.Count) ?  Data.Rows[this.SelectedRow] : null;
 
-            if (Options.Contains(DynamicGridOption.DirectEdit) && !OpenEditorOnDirectEdit)
+            if (HasOption(DynamicGridOption.DirectEdit) && !OpenEditorOnDirectEdit)
             {
                 if (!CanCreateItems())
                     return;
@@ -3585,7 +3596,7 @@ namespace InABox.DynamicGrid
         private void SelectColumnsClick(object sender, RoutedEventArgs e)
         {
             var editor = new DynamicGridColumnsEditor(typeof(T));
-            editor.DirectEdit = Options.Contains(DynamicGridOption.DirectEdit);
+            editor.DirectEdit = HasOption(DynamicGridOption.DirectEdit);
 
             editor.Columns.AddRange(VisibleColumns);
 
@@ -3614,7 +3625,7 @@ namespace InABox.DynamicGrid
         {
             Logger.Send(LogType.Information,"","DataGrid_Drop");
             
-            if (!Options.Contains(DynamicGridOption.DragTarget))
+            if (!HasOption(DynamicGridOption.DragTarget))
                 return;
             
             Logger.Send(LogType.Information,"","DataGrid_Drop::DragTarget==true");
@@ -3673,7 +3684,7 @@ namespace InABox.DynamicGrid
             Logger.Send(LogType.Information,"","RowDragDropController_DragStart");
             //e.Handled = true;
             
-            if (!Options.Contains(DynamicGridOption.DragSource))
+            if (!HasOption(DynamicGridOption.DragSource))
                 return;
             
             var rows = new List<CoreRow>();
@@ -3888,7 +3899,7 @@ namespace InABox.DynamicGrid
 
         private void CheckPreviewMouseDown(object sender, MouseButtonEventArgs e)
         {
-            if (!Options.Contains(DynamicGridOption.DragSource))
+            if (!HasOption(DynamicGridOption.DragSource))
                 return;
             if (e.LeftButton == MouseButtonState.Pressed)
             {
@@ -3901,7 +3912,7 @@ namespace InABox.DynamicGrid
         //{
         //    Logger.Send(LogType.Information, this.GetType().EntityName(), String.Format("Checking Mouse Move: StartPoint = {0},{1}", startpoint.X, startpoint.Y));
 
-        //    if (!_Options.Contains(DynamicGridOptions.DragSource))
+        //    if (!_HasOption(DynamicGridOptions.DragSource))
         //        return;
         //    Vector diff = startpoint - e.GetPosition(null);
         //    Logger.Send(LogType.Information, this.GetType().EntityName(), String.Format("Checking Mouse Move: StartPoint = {0},{1} Diff = {2},{3}", startpoint.X, startpoint.Y, diff.X, diff.Y));
@@ -3919,7 +3930,7 @@ namespace InABox.DynamicGrid
 
         private void CheckPreviewMouseUp(object sender, MouseButtonEventArgs e)
         {
-            if (!Options.Contains(DynamicGridOption.DragSource))
+            if (!HasOption(DynamicGridOption.DragSource))
                 return;
 
             Logger.Send(LogType.Information, GetType().EntityName(), "Clearing Start Point");

+ 1 - 0
inabox.wpf/DynamicGrid/DynamicGridColumnsEditor.xaml.cs

@@ -1,5 +1,6 @@
 using InABox.Wpf;
 using System;
+using System.Collections.Generic;
 using System.Windows;
 using System.Windows.Controls;
 

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

@@ -114,7 +114,7 @@ namespace InABox.DynamicGrid
 
         public virtual void Load(object item, Func<Type, CoreTable>? PageDataHandler)
         {
-            Reconfigure(Options);
+            Reconfigure();
 
             Item = (TOne)item;
             

+ 11 - 9
inabox.wpf/DynamicGrid/Editors/EmbeddedListEditor/EmbeddedListEditorControl.cs

@@ -46,15 +46,17 @@ namespace InABox.DynamicGrid
             
             var grid = (Activator.CreateInstance(gridtype) as IDynamicItemsListGrid)!;
             grid.Items = list as IEnumerable<object>;
-            grid.DefaultOptions
-                .BeginUpdate()
-                .Add(DynamicGridOption.AddRows)
-                .Add(DynamicGridOption.EditRows)
-                .Add(DynamicGridOption.DeleteRows)
-                .Add(DynamicGridOption.RecordCount);
-            if (EditorDefinition.DirectEdit)
-                grid.DefaultOptions.Add(DynamicGridOption.DirectEdit);
-            grid.DefaultOptions.EndUpdate();
+            grid.Reconfigure(options =>
+            {
+                options.BeginUpdate()
+                    .Add(DynamicGridOption.AddRows)
+                    .Add(DynamicGridOption.EditRows)
+                    .Add(DynamicGridOption.DeleteRows)
+                    .Add(DynamicGridOption.RecordCount);
+                if (EditorDefinition.DirectEdit)
+                    options.Add(DynamicGridOption.DirectEdit);
+                options.EndUpdate();
+            });
             grid.Refresh(true, true);
 
             EditorDefinition.CreateButtons(grid);

+ 5 - 10
inabox.wpf/DynamicGrid/Editors/LookupEditor/LookupEditorControl.cs

@@ -77,7 +77,7 @@ namespace InABox.DynamicGrid
             Editor.Items.Clear();
             Lookups.Clear();
 
-            if (!IsEnumEditor())
+            if (!EditorDefinition.IsEnumEditor())
                 Editor.Items.Add("");
             foreach (var row in values.Rows)
             {
@@ -92,7 +92,7 @@ namespace InABox.DynamicGrid
             }
 
             var sel = value != null ? values.Rows.FirstOrDefault(r => r[keycol].Equals(value)) : null;
-            if (IsEnumEditor())
+            if (EditorDefinition.IsEnumEditor())
                 Editor.SelectedIndex = sel != null ? sel.Index : 0;
             else
                 Editor.SelectedIndex = sel != null ? sel.Index + 1 : 0;
@@ -116,11 +116,6 @@ namespace InABox.DynamicGrid
             Editor.Focus();
         }
 
-        private bool IsEnumEditor()
-        {
-            return EditorDefinition is EnumLookupEditor;
-        }
-
         public List<Button> Buttons { get; private set; }
 
         protected override FrameworkElement CreateEditor()
@@ -186,7 +181,7 @@ namespace InABox.DynamicGrid
 
         protected override object RetrieveValue()
         {
-            if (IsEnumEditor())
+            if (EditorDefinition.IsEnumEditor())
             {
                 if (Editor.SelectedIndex >= 0 && Editor.SelectedIndex < Lookups.Keys.Count)
                     return Lookups.Keys.ElementAt(Editor.SelectedIndex);
@@ -218,13 +213,13 @@ namespace InABox.DynamicGrid
                 Editor.Items.Clear();
                 Editor.Items.Add("");
                 Editor.Items.Add("Loading...");
-                Editor.SelectedIndex = IsEnumEditor() ? 0 : 1;
+                Editor.SelectedIndex = EditorDefinition.IsEnumEditor() ? 0 : 1;
                 return;
             }
 
             if (Lookups.ContainsKey(value))
             {
-                if (IsEnumEditor())
+                if (EditorDefinition.IsEnumEditor())
                     Editor.SelectedIndex = Lookups.Keys.ToList().IndexOf(value);
                 else
                     Editor.SelectedIndex = Lookups.Keys.ToList().IndexOf(value) + 1;

+ 8 - 5
inabox.wpf/DynamicGrid/Editors/PopupEditor/PopupList.xaml.cs

@@ -69,11 +69,14 @@ namespace InABox.DynamicGrid
             }
 
             layoutGrid.Children.Add((UIElement)_grid);
-
-            _grid.DefaultOptions.BeginUpdate().Clear().AddRange(
-                DynamicGridOption.SelectColumns,
-                DynamicGridOption.FilterRows
-            ).EndUpdate();
+            
+            _grid.Reconfigure(options =>
+            {
+                options.BeginUpdate().Clear().AddRange(
+                    DynamicGridOption.SelectColumns,
+                    DynamicGridOption.FilterRows
+                ).EndUpdate();
+            });
 
             CoreUtils.SetPropertyValue(_grid, "ColumnsTag", "Popup");
 

+ 15 - 4
inabox.wpf/DynamicGrid/IDynamicGrid.cs

@@ -35,8 +35,6 @@ namespace InABox.DynamicGrid
         double FontSize { get; set; }
         void Refresh(bool columns, bool data);
 
-        public abstract void Reconfigure();
-
         void InitialiseEditorForm(IDynamicEditorForm editor, object[] items, Func<Type, CoreTable>? pageDataHandler = null, bool preloadPages = false);
         bool EditItems(object[] items, Func<Type, CoreTable>? PageDataHandler = null, bool PreloadPages = false);
 
@@ -49,8 +47,21 @@ namespace InABox.DynamicGrid
 
         delegate void ReconfigureEvent(FluentList<DynamicGridOption> options);
         event ReconfigureEvent? OnReconfigure;
-        
-        FluentList<DynamicGridOption> DefaultOptions { get; }
+
+        public abstract void Reconfigure();
+
+        /// <summary>
+        /// Add <paramref name="onReconfigure"/> to <see cref="OnReconfigure"/>, and then call <see cref="Reconfigure"/>.
+        /// </summary>
+        /// <remarks>
+        /// Probably should only be called once per grid, otherwise there will be multiple event handlers bound.<br/>
+        /// If you want to reconfigure without specifiying
+        /// a new reconfigure event, use <see cref="Reconfigure"/>.
+        /// </remarks>
+        /// <param name="onReconfigure"></param>
+        public void Reconfigure(ReconfigureEvent onReconfigure);
+
+        public bool HasOption(DynamicGridOption option);
 
         void AddVisualFilter(string column, string value, FilterType filtertype = FilterType.Contains);
 

+ 15 - 11
inabox.wpf/DynamicGrid/MasterList.xaml.cs

@@ -51,22 +51,26 @@ namespace InABox.DynamicGrid
 
             layoutGrid.Children.Add((UIElement)grid);
 
-            grid.DefaultOptions.BeginUpdate();
-            grid.DefaultOptions.AddRange(
-                DynamicGridOption.SelectColumns,
-                DynamicGridOption.FilterRows,
-                DynamicGridOption.ShowHelp
-            );
-
             DataModelType = typeof(AutoDataModel<>).MakeGenericType(type);
-            if (DataModelType != null)
-                grid.DefaultOptions.Add(DynamicGridOption.Print);
+
+            grid.Reconfigure(options =>
+            {
+                options.BeginUpdate();
+                options.AddRange(
+                    DynamicGridOption.SelectColumns,
+                    DynamicGridOption.FilterRows,
+                    DynamicGridOption.ShowHelp
+                );
+
+                if (DataModelType != null)
+                    options.Add(DynamicGridOption.Print);
+
+                options.EndUpdate();
+            });
 
             if (!string.IsNullOrWhiteSpace(GroupBy))
                 grid.AddHiddenColumn(GroupBy);
 
-            grid.DefaultOptions.EndUpdate();
-
             grid.OnPrintData += PrintData;
 
             grid.AfterRefresh += Grid_AfterReload;

+ 9 - 6
inabox.wpf/DynamicGrid/MultiSelectDialog.cs

@@ -49,12 +49,15 @@ namespace InABox.DynamicGrid
 
             datagrid = new DynamicDataGrid<T>();
 
-            datagrid.DefaultOptions.BeginUpdate();
-            datagrid.DefaultOptions.Clear();
-            datagrid.DefaultOptions.AddRange(DynamicGridOption.SelectColumns, DynamicGridOption.FilterRows);
-            if (multiselect)
-                datagrid.DefaultOptions.Add(DynamicGridOption.MultiSelect);
-            datagrid.DefaultOptions.EndUpdate();
+            datagrid.Reconfigure(options =>
+            {
+                options.BeginUpdate();
+                options.Clear();
+                options.AddRange(DynamicGridOption.SelectColumns, DynamicGridOption.FilterRows);
+                if (multiselect)
+                    options.Add(DynamicGridOption.MultiSelect);
+                options.EndUpdate();
+            });
 
             datagrid.OnReload += Grid_OnReload;
             datagrid.OnDoubleClick += Grid_DoubleClick;