|  | @@ -28,7 +28,6 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |          private TMany[] MasterList = Array.Empty<TMany>();
 | 
	
		
			
				|  |  |          private readonly PropertyInfo property;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public PageType PageType => PageType.Other;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          protected DynamicGridCustomColumnsComponent<TMany> ColumnsComponent;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -68,42 +67,46 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |              options.EndUpdate();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private bool _readOnly;
 | 
	
		
			
				|  |  | -        public bool ReadOnly
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            get => _readOnly;
 | 
	
		
			
				|  |  | -            set
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if(_readOnly != value)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    _readOnly = value;
 | 
	
		
			
				|  |  | -                    Reconfigure();
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          private static bool IsAutoEntity => typeof(TMany).HasAttribute<AutoEntity>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          protected Filters<TMany> Criteria { get; } = new Filters<TMany>();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          public TOne Item { get; protected set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public bool Ready { get; set; }
 | 
	
		
			
				|  |  | +        public List<TMany> Items { get; private set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public DynamicEditorGrid EditorGrid { get; set; }
 | 
	
		
			
				|  |  | +        public void LoadItems(TMany[] items)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Items.Clear();
 | 
	
		
			
				|  |  | +            Items.AddRange(items);
 | 
	
		
			
				|  |  | +            Refresh(false, true);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public string Caption()
 | 
	
		
			
				|  |  | +        private static string GetTag()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var caption = typeof(TMany).GetCustomAttribute(typeof(Caption));
 | 
	
		
			
				|  |  | -            if (caption != null)
 | 
	
		
			
				|  |  | -                return ((Caption)caption).Text;
 | 
	
		
			
				|  |  | -            var result = new Inflector.Inflector(new CultureInfo("en")).Pluralize(typeof(TMany).Name);
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | +            return typeof(TOne).Name + "." + typeof(TMany).Name;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        public virtual int Order()
 | 
	
		
			
				|  |  | +        #region IDynamicEditorPage
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public DynamicEditorGrid EditorGrid { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public PageType PageType => PageType.Other;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public bool Ready { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private bool _readOnly;
 | 
	
		
			
				|  |  | +        public bool ReadOnly
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return int.MinValue;
 | 
	
		
			
				|  |  | +            get => _readOnly;
 | 
	
		
			
				|  |  | +            set
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (_readOnly != value)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    _readOnly = value;
 | 
	
		
			
				|  |  | +                    Reconfigure();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          public virtual void Load(object item, Func<Type, CoreTable?>? PageDataHandler)
 | 
	
	
		
			
				|  | @@ -111,7 +114,9 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |              Reconfigure();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Item = (TOne)item;
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Refresh(true, false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              var data = PageDataHandler?.Invoke(typeof(TMany));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (data == null)
 | 
	
	
		
			
				|  | @@ -128,14 +133,14 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |                      criteria.Add(new Filter<TMany>(exp).IsEqualTo(Item.ID).And(exp).IsNotEqualTo(Guid.Empty));
 | 
	
		
			
				|  |  |                      criteria.AddRange(Criteria.Items);
 | 
	
		
			
				|  |  |                      var sort = LookupFactory.DefineSort<TMany>();
 | 
	
		
			
				|  |  | -                    data = new Client<TMany>().Query(criteria.Combine(), null, sort);
 | 
	
		
			
				|  |  | +                    data = new Client<TMany>().Query(criteria.Combine(), DynamicGridUtils.LoadEditorColumns(DataColumns()), sort);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              MasterList = data.Rows.Select(x => x.ToObject<TMany>()).ToArray();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Items = MasterList.ToList();
 | 
	
		
			
				|  |  | -            Refresh(true, true);
 | 
	
		
			
				|  |  | +            Refresh(false, true);
 | 
	
		
			
				|  |  |              Ready = true;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -144,16 +149,7 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |              // Don't need to do anything here
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        protected virtual void OnDeleteItem(TMany item)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (IsAutoEntity)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            new Client<TMany>().Delete(item, typeof(TMany).Name + " Deleted by User");
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public void AfterSave(object item)
 | 
	
		
			
				|  |  | +        public virtual void AfterSave(object item)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              if (IsAutoEntity)
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -174,6 +170,39 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |              new Client<TMany>().Save(Items.Where(x => x.IsChanged()), "Updated by User");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        public Size MinimumSize()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return new Size(400, 400);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public string Caption()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var caption = typeof(TMany).GetCustomAttribute(typeof(Caption));
 | 
	
		
			
				|  |  | +            if (caption != null)
 | 
	
		
			
				|  |  | +                return ((Caption)caption).Text;
 | 
	
		
			
				|  |  | +            var result = new Inflector.Inflector(new CultureInfo("en")).Pluralize(typeof(TMany).Name);
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public virtual int Order()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return int.MinValue;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #endregion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #region DynamicGrid
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected virtual void OnDeleteItem(TMany item)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (IsAutoEntity)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            new Client<TMany>().Delete(item, typeof(TMany).Name + " Deleted by User");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          protected override CoreTable LoadImportKeys(string[] fields)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var result = base.LoadImportKeys(fields);
 | 
	
	
		
			
				|  | @@ -193,25 +222,6 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              return result;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public Size MinimumSize()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return new Size(400, 400);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public List<TMany> Items { get; private set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        public void LoadItems(TMany[] items)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            Items.Clear();
 | 
	
		
			
				|  |  | -            Items.AddRange(items);
 | 
	
		
			
				|  |  | -            Refresh(false, true);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        private static string GetTag()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return typeof(TOne).Name + "." + typeof(TMany).Name;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          public override DynamicGridColumns GenerateColumns()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var cols = new DynamicGridColumns();
 | 
	
	
		
			
				|  | @@ -282,7 +292,7 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |          protected override void DeleteItems(params CoreRow[] rows)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var items = rows.Select(LoadItem).ToList();
 | 
	
		
			
				|  |  | -            foreach(var item in items)
 | 
	
		
			
				|  |  | +            foreach (var item in items)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  Items.Remove(item);
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -342,14 +352,17 @@ namespace InABox.DynamicGrid
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          protected override bool BeforePaste(IEnumerable<TMany> items, ClipAction action)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if(action == ClipAction.Copy)
 | 
	
		
			
				|  |  | +            if (action == ClipAction.Copy)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                foreach(var item in items)
 | 
	
		
			
				|  |  | +                foreach (var item in items)
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      item.ID = Guid.Empty;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              return base.BeforePaste(items, action);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #endregion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |