Bläddra i källkod

DON'T PULL
- Work on the Data component code

Kenric Nugteren 11 månader sedan
förälder
incheckning
99124564a3

+ 2 - 2
InABox.Core/CoreUtils.cs

@@ -780,8 +780,8 @@ namespace InABox.Core
             if (o is BaseObject)
             {
                 var property = DatabaseSchema.Property(t, name);
-                if (property != null && (property is CustomProperty || !name.Contains(".")))
-                    return property.Getter().Invoke(o);
+                if (property != null)
+                    return property.Getter()(o);
             }
 
             var props = name.Split('.');

+ 29 - 110
inabox.wpf/DynamicGrid/DataComponent/DynamicGridClientDataComponent.cs

@@ -28,15 +28,12 @@ public class DynamicGridClientDataComponent<T> : IDynamicGridDataComponent<T>
 
     public Column<T>[] FilterColumns;
 
-    private Button MergeBtn;
-
     public DynamicGridClientDataComponent(DynamicGrid<T> grid)
     {
         Grid = grid;
 
-        MergeBtn = Grid.AddButton("Merge", Wpf.Resources.merge.AsBitmapImage(Color.White), DoMerge);
-
-        Grid.OnSelectItem += Grid_OnSelectItem;
+        Grid.BeforeRefresh += Grid_BeforeRefresh;
+        Grid.AfterRefresh += Grid_AfterRefresh;
 
         SetupFilterColumns();
     }
@@ -67,21 +64,39 @@ public class DynamicGridClientDataComponent<T> : IDynamicGridDataComponent<T>
         }
     }
 
+    private CoreRow[]? SelectedBeforeRefresh;
 
-    private void Grid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
+    private void Grid_BeforeRefresh(object sender, BeforeRefreshEventArgs args)
     {
-        MergeBtn.Visibility = Grid.Options.MultiSelect && typeof(T).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge<T>()
-            && e.Rows != null && e.Rows.Length > 1
-            ? Visibility.Visible
-            : Visibility.Collapsed;
+        SelectedBeforeRefresh = Grid.SelectedRows;
     }
 
-    public bool OptionsChanged()
+    private void Grid_AfterRefresh(object sender, AfterRefreshEventArgs args)
     {
-        if (MergeBtn != null)
-            MergeBtn.Visibility = Visibility.Collapsed;
+        if (SelectedBeforeRefresh is not null)
+        {
+            var selectedValues = SelectedBeforeRefresh
+                .Select(x => FilterColumns.Select(c => x[c.Property]).ToList())
+                .ToList();
+
+            SelectedBeforeRefresh = null;
+
+            var selectedRows = Grid.Data.Rows.Where(r =>
+            {
+                return selectedValues.Any(v =>
+                {
+                    for (int i = 0; i < v.Count; ++i)
+                    {
+                        if (v[i]?.Equals(r[FilterColumns[i].Property]) != true)
+                            return false;
+                    }
+                    return true;
+                });
+            }).ToArray();
 
-        return false;
+            Grid.SelectedRows = selectedRows;
+            Grid.SelectItems(selectedRows);
+        }
     }
 
     public Columns<T> LoadEditorColumns()
@@ -164,8 +179,6 @@ public class DynamicGridClientDataComponent<T> : IDynamicGridDataComponent<T>
         Client.Save(items, "Edited by User");
     }
 
-    protected bool IsPaging { get; private set; } = false;
-
     public void Reload(
         Filters<T> criteria, Columns<T> columns, SortOrder<T>? sort,
         CancellationToken token, Action<QueryResult> action)
@@ -215,98 +228,4 @@ public class DynamicGridClientDataComponent<T> : IDynamicGridDataComponent<T>
             Client.Query(criteria.Combine(), columns, sort, (data, e) => action(data is not null ? new(data) : new(e!)));
         }
     }
-
-    #region Merge
-
-    private bool DoMerge(Button arg1, CoreRow[] arg2)
-    {
-        if (arg2 == null || arg2.Length <= 1)
-            return false;
-        var targetid = arg2.Last().Get<T, Guid>(x => x.ID);
-        var target = arg2.Last().ToObject<T>().ToString();
-        var otherids = arg2.Select(r => r.Get<T, Guid>(x => x.ID)).Where(x => x != targetid).ToArray();
-        string[] others = arg2.Where(r => otherids.Contains(r.Get<Guid>("ID"))).Select(x => x.ToObject<T>().ToString()!).ToArray();
-        var rows = arg2.Length;
-        if (MessageBox.Show(
-                string.Format(
-                    "This will merge the following items:\n\n- {0}\n\n into:\n\n- {1}\n\nAfter this, the items will be permanently removed.\nAre you sure you wish to do this?",
-                    string.Join("\n- ", others),
-                    target
-                ),
-                "Merge Items Warning",
-                MessageBoxButton.YesNo,
-                MessageBoxImage.Stop) != MessageBoxResult.Yes
-           )
-            return false;
-
-        using (new WaitCursor())
-        {
-            var types = CoreUtils.Entities.Where(
-                x =>
-                    x.IsClass
-                    && !x.IsGenericType
-                    && x.IsSubclassOf(typeof(Entity))
-                    && !x.Equals(typeof(AuditTrail))
-                    && !x.Equals(typeof(T))
-                    && x.GetCustomAttribute<AutoEntity>() == null
-                    && x.HasInterface<IRemotable>()
-                    && x.HasInterface<IPersistent>()
-            ).ToArray();
-
-            foreach (var type in types)
-            {
-                var props = CoreUtils.PropertyList(
-                    type,
-                    x =>
-                        x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
-                        && x.PropertyType.GetInheritedGenericTypeArguments().Contains(typeof(T))
-                );
-                foreach (var prop in props)
-                {
-                    var propname = string.Format(prop.Name + ".ID");
-                    var filter = Core.Filter.Create(type);
-                    filter.Expression = CoreUtils.CreateMemberExpression(type, propname);
-                    filter.Operator = Operator.InList;
-                    filter.Value = otherids;
-                    var columns = Columns.None(type)
-                        .Add("ID")
-                        .Add(propname);
-                    var updates = ClientFactory.CreateClient(type).Query(filter, columns).Rows.Select(r => r.ToObject(type)).ToArray();
-                    if (updates.Any())
-                    {
-                        foreach (var update in updates)
-                            CoreUtils.SetPropertyValue(update, propname, targetid);
-                        ClientFactory.CreateClient(type).Save(updates,
-                            string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
-                    }
-                }
-            }
-
-            var histories = new Client<AuditTrail>()
-                .Query(
-                    new Filter<AuditTrail>(x => x.EntityID).InList(otherids),
-                    Columns.None<AuditTrail>()
-                        .Add(x => x.ID).Add(x => x.EntityID))
-                .ToArray<AuditTrail>();
-            foreach (var history in histories)
-                history.EntityID = targetid;
-            if (histories.Length != 0)
-                new Client<AuditTrail>().Save(histories, "");
-
-            var deletes = new List<object>();
-            foreach (var otherid in otherids)
-            {
-                var delete = new T();
-                CoreUtils.SetPropertyValue(delete, "ID", otherid);
-                deletes.Add(delete);
-            }
-
-            ClientFactory.CreateClient(typeof(T))
-                .Delete(deletes, string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
-            return true;
-        }
-    }
-
-
-    #endregion
 }

+ 112 - 147
inabox.wpf/DynamicGrid/DynamicDataGrid.cs

@@ -77,6 +77,17 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         var dataComponent = new DynamicGridClientDataComponent<TEntity>(this);
         dataComponent.OnReload += DataComponent_OnReload;
         DataComponent = dataComponent;
+
+        MergeBtn = AddButton("Merge", Wpf.Resources.merge.AsBitmapImage(Color.White), DoMerge);
+    }
+
+    protected override void SelectItems(CoreRow[]? rows)
+    {
+        base.SelectItems(rows);
+        MergeBtn.Visibility = Options.MultiSelect && typeof(T).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge<TEntity>()
+            && rows != null && rows.Length > 1
+            ? Visibility.Visible
+            : Visibility.Collapsed;
     }
 
     private void DataComponent_OnReload(object sender, Filters<TEntity> criteria, Columns<TEntity> columns, ref SortOrder<TEntity>? sortby)
@@ -89,6 +100,9 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         base.OptionsChanged();
 
         FilterComponent.ShowFilterList = Options.FilterRows && !Options.HideDatabaseFilters;
+
+        if (MergeBtn != null)
+            MergeBtn.Visibility = Visibility.Collapsed;
     }
 
     protected override void DoReconfigure(DynamicGridOptions options)
@@ -125,83 +139,6 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         }
     }
 
-    protected override string FormatRecordCount(int count)
-    {
-        return IsPaging 
-            ? $"{base.FormatRecordCount(count)} (loading..)"
-            : base.FormatRecordCount(count);
-    }
-
-    private CoreRow[]? SelectedBeforeRefresh;
-    protected override void OnAfterRefresh()
-    {
-        base.OnAfterRefresh();
-
-        if (SelectedBeforeRefresh is not null)
-        {
-            var selectedValues = SelectedBeforeRefresh
-                .Select(x => FilterColumns.Select(c => x[c.Property]).ToList())
-                .ToList();
-
-            SelectedBeforeRefresh = null;
-
-            var selectedRows = Data.Rows.Where(r =>
-            {
-                return selectedValues.Any(v =>
-                {
-                    for (int i = 0; i < v.Count; ++i)
-                    {
-                        if (v[i]?.Equals(r[FilterColumns[i].Property]) != true)
-                            return false;
-                    }
-                    return true;
-                });
-            }).ToArray();
-
-            SelectedRows = selectedRows;
-            SelectItems(selectedRows);
-        }
-    }
-
-    public override void Refresh(bool reloadcolumns, bool reloaddata)
-    {
-        SelectedBeforeRefresh = SelectedRows;
-        base.Refresh(reloadcolumns, reloaddata);
-    }
-
-    private object GetPropertyValue(Expression member, object obj)
-    {
-        var objectMember = Expression.Convert(member, typeof(object));
-
-        var getterLambda = Expression.Lambda<Func<object>>(objectMember);
-
-        var getter = getterLambda.Compile();
-
-        return getter();
-    }
-
-    protected override void ObjectToRow(TEntity obj, CoreRow row)
-    {
-        foreach (var column in Data.Columns)
-        {
-            var prop = DatabaseSchema.Property(obj.GetType(), column.ColumnName);
-            if (prop is StandardProperty)
-                row.Set(column.ColumnName, CoreUtils.GetPropertyValue(obj, prop.Name));
-            else if (prop is CustomProperty)
-                row.Set(column.ColumnName, obj.UserProperties[column.ColumnName]);
-        }
-
-        //base.ObjectToRow(obj, row);
-    }
-
-    //private void Auditgrid_OnReload(object sender, Dictionary<string, object> criteria, ref String sort)
-    //{
-    //	criteria["DocumentType"] = typeof(TEntity).EntityName();
-    //	criteria["DocumentID"] = (sender as FrameworkElement).Tag;
-
-    //	sort = "TimeStamp";
-    //}
-
     public override void LoadEditorButtons(TEntity item, DynamicEditorButtons buttons)
     {
         base.LoadEditorButtons(item, buttons);
@@ -209,9 +146,9 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
             buttons.Add("Audit Trail", Wpf.Resources.view.AsBitmapImage(), item, AuditTrailClick);
     }
 
-    private void AuditTrailClick(object sender, object item)
+    private void AuditTrailClick(object sender, object? item)
     {
-        var entity = (TEntity)item;
+        var entity = (item as TEntity)!;
         var window = new AuditWindow(entity.ID);
         window.ShowDialog();
     }
@@ -260,42 +197,7 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         new UserConfiguration<DynamicGridSettings>(tag).Save(settings);
     }
 
-    protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
-    {
-        var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == column.ColumnName);
-        if (prop != null)
-            return prop.Editor;
-        return base.GetEditor(item, column);
-    }
-
-    protected override object? GetEditorValue(object item, string name)
-    {
-        if (item is TEntity entity)
-        {
-            var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == name);
-            if (prop is CustomProperty)
-            {
-                if (entity.UserProperties.ContainsKey(name))
-                    return entity.UserProperties[name];
-                return null;
-            }
-        }
-
-        return base.GetEditorValue(item, name);
-    }
-
-    protected override void SetEditorValue(object item, string name, object value)
-    {
-        var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == name);
-        if (prop is CustomProperty && item is TEntity entity)
-        {
-            entity.UserProperties[name] = value;
-        }
-        else
-        {
-            base.SetEditorValue(item, name, value);
-        }
-    }
+    #region Duplicate
 
     protected bool Duplicate(
         CoreRow row,
@@ -417,6 +319,8 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         return rows.Select(x => x.ToObject<TEntity>());
     }
 
+    #endregion
+
     protected override bool BeforePaste(IEnumerable<TEntity> items, ClipAction action)
     {
         if (action == ClipAction.Copy)
@@ -429,38 +333,6 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         return base.BeforePaste(items, action);
     }
 
-    protected override void CustomiseExportFilters(Filters<TEntity> filters, CoreRow[] visiblerows)
-    {
-        base.CustomiseExportFilters(filters, visiblerows);
-
-        /*if (IsEntity)
-        {
-            var ids = visiblerows.Select(r => r.Get<TEntity, Guid>(c => c.ID)).ToArray();
-            filters.Add(new Filter<TEntity>(x => x.ID).InList(ids));
-        }
-        else
-        {
-            Filter<TEntity>? filter = null;
-
-            foreach (var row in visiblerows)
-            {
-                var rowFilter = GetRowFilter(row);
-                if(rowFilter is not null)
-                {
-                    if (filter is null)
-                    {
-                        filter = rowFilter;
-                    }
-                    else
-                    {
-                        filter.Or(rowFilter);
-                    }
-                }
-            }
-            filters.Add(filter);
-        }*/
-    }
-
     protected override IEnumerable<Tuple<Type?, CoreTable>> LoadExportTables(Filters<TEntity> filter, IEnumerable<Tuple<Type, IColumns>> tableColumns)
     {
         var queries = new Dictionary<string, IQueryDef>();
@@ -515,4 +387,97 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         return Client.Query(null, Columns.None<TEntity>().Add(fields));
     }
     
+
+    #region Merge
+
+    private bool DoMerge(Button arg1, CoreRow[] arg2)
+    {
+        if (arg2 == null || arg2.Length <= 1)
+            return false;
+        var targetid = arg2.Last().Get<T, Guid>(x => x.ID);
+        var target = arg2.Last().ToObject<T>().ToString();
+        var otherids = arg2.Select(r => r.Get<T, Guid>(x => x.ID)).Where(x => x != targetid).ToArray();
+        string[] others = arg2.Where(r => otherids.Contains(r.Get<Guid>("ID"))).Select(x => x.ToObject<T>().ToString()!).ToArray();
+        var rows = arg2.Length;
+        if (MessageBox.Show(
+                string.Format(
+                    "This will merge the following items:\n\n- {0}\n\n into:\n\n- {1}\n\nAfter this, the items will be permanently removed.\nAre you sure you wish to do this?",
+                    string.Join("\n- ", others),
+                    target
+                ),
+                "Merge Items Warning",
+                MessageBoxButton.YesNo,
+                MessageBoxImage.Stop) != MessageBoxResult.Yes
+           )
+            return false;
+
+        using (new WaitCursor())
+        {
+            var types = CoreUtils.Entities.Where(
+                x =>
+                    x.IsClass
+                    && !x.IsGenericType
+                    && x.IsSubclassOf(typeof(Entity))
+                    && !x.Equals(typeof(AuditTrail))
+                    && !x.Equals(typeof(T))
+                    && x.GetCustomAttribute<AutoEntity>() == null
+                    && x.HasInterface<IRemotable>()
+                    && x.HasInterface<IPersistent>()
+            ).ToArray();
+
+            foreach (var type in types)
+            {
+                var props = CoreUtils.PropertyList(
+                    type,
+                    x =>
+                        x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
+                        && x.PropertyType.GetInheritedGenericTypeArguments().Contains(typeof(T))
+                );
+                foreach (var prop in props)
+                {
+                    var propname = string.Format(prop.Name + ".ID");
+                    var filter = Core.Filter.Create(type);
+                    filter.Expression = CoreUtils.CreateMemberExpression(type, propname);
+                    filter.Operator = Operator.InList;
+                    filter.Value = otherids;
+                    var columns = Columns.None(type)
+                        .Add("ID")
+                        .Add(propname);
+                    var updates = ClientFactory.CreateClient(type).Query(filter, columns).Rows.Select(r => r.ToObject(type)).ToArray();
+                    if (updates.Any())
+                    {
+                        foreach (var update in updates)
+                            CoreUtils.SetPropertyValue(update, propname, targetid);
+                        ClientFactory.CreateClient(type).Save(updates,
+                            string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
+                    }
+                }
+            }
+
+            var histories = new Client<AuditTrail>()
+                .Query(
+                    new Filter<AuditTrail>(x => x.EntityID).InList(otherids),
+                    Columns.None<AuditTrail>()
+                        .Add(x => x.ID).Add(x => x.EntityID))
+                .ToArray<AuditTrail>();
+            foreach (var history in histories)
+                history.EntityID = targetid;
+            if (histories.Length != 0)
+                new Client<AuditTrail>().Save(histories, "");
+
+            var deletes = new List<object>();
+            foreach (var otherid in otherids)
+            {
+                var delete = new T();
+                CoreUtils.SetPropertyValue(delete, "ID", otherid);
+                deletes.Add(delete);
+            }
+
+            ClientFactory.CreateClient(typeof(T))
+                .Delete(deletes, string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
+            return true;
+        }
+    }
+
+    #endregion
 }

+ 20 - 21
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -498,8 +498,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         Count.Content = FormatRecordCount(count);
     }
 
-    protected virtual string FormatRecordCount(int count) => $"{count} Records";
-    
+    protected virtual string FormatRecordCount(int count) => IsPaging ? $"{count} Records (Loading...)" : $"{count} Records";
 
     void IDynamicGridUIComponentParent<T>.LoadColumnsMenu(ContextMenu menu)
     {
@@ -836,7 +835,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     /// Call the <see cref="OnSelectItem"/> event, and do any updating which needs to occur when items are selected.
     /// </summary>
     /// <param name="rows"></param>
-    protected virtual void SelectItems(CoreRow[]? rows)
+    public virtual void SelectItems(CoreRow[]? rows)
     {
         if (IsReady)
             OnSelectItem?.Invoke(this, new DynamicGridSelectionEventArgs(rows));
@@ -1016,6 +1015,9 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     }
 
     private CancellationTokenSource? RefreshCancellationToken;
+
+    protected bool IsPaging { get; private set; } = false;
+
     public virtual void Refresh(bool reloadcolumns, bool reloaddata)
     {
         if (bRefreshing)
@@ -1063,6 +1065,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
                 result.DoWith(
                     table =>
                     {
+                        IsPaging = result.IsPaged;
                         if (table.Offset == 0 || MasterData is null)
                         {
                             MasterData = table;
@@ -1140,6 +1143,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
     protected virtual void OnAfterRefresh()
     {
+        DataComponent.AfterRefresh();
     }
 
     protected void DoAfterRefresh()
@@ -1284,19 +1288,6 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         {
             var _newRows = FilterRows(Enumerable.Range(range.RowIdx, range.Size).Select(i => MasterData.Rows[i]), Data, _recordmap);
             UIComponent.AddPage(_newRows);
-            /*
-            semaphore.Wait();
-            try
-            {
-                // This throws errors when overalpping refreshes cause a mismatch between MasterData and range
-                // Using try/finally and a Semaphore as a temporary measure until we can isolate the issue
-                var _newRows = FilterRows(Enumerable.Range(range.RowIdx, range.Size).Select(i => MasterData.Rows[i]), Data, _recordmap);
-                UIComponent.AddPage(_newRows);
-            }
-            finally
-            {
-                semaphore.Release();
-            }*/
         }
     }
 
@@ -1695,6 +1686,10 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
     /// <returns>A new editor, or <see langword="null"/> if no editor defined and no sensible default exists.</returns>
     protected virtual BaseEditor? GetEditor(object item, DynamicGridColumn column)
     {
+        var prop = DatabaseSchema.Property(typeof(T), column.ColumnName);
+        if (prop != null)
+            return prop.Editor;
+
         return column.Editor ?? CoreUtils.GetProperty(item.GetType(), column.ColumnName).GetEditor();
     }
 
@@ -1705,6 +1700,15 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
     protected virtual void SetEditorValue(object item, string name, object value)
     {
+        if (item is T obj)
+        {
+            var prop = DatabaseSchema.Property(typeof(T), name);
+            if (prop is not null)
+            {
+                prop.Setter()(obj, value);
+                return;
+            }
+        }
         try
         {
             CoreUtils.SetPropertyValue(item, name, value);
@@ -1715,11 +1719,6 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
         }
     }
 
-    protected virtual object? GetEditorValue(object item, string name)
-    {
-        return CoreUtils.GetPropertyValue(item, name);
-    }
-
     protected virtual bool CanCreateItems()
     {
         return true;