123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using InABox.Core;
- using System.Diagnostics.CodeAnalysis;
- namespace InABox.Mobile
- {
- public abstract class ListModel<TParent, TItem, TEntity> : Model<TParent,TItem,TEntity>, IListModel<TParent, TItem, TEntity>, IEnumerable<TItem>
- where TParent : ListModel<TParent, TItem, TEntity>
- where TEntity : Entity, IRemotable, IPersistent, new()
- where TItem : Shell<TParent,TEntity>, new()
- {
- protected ListModel(IModelHost host, Func<Filter<TEntity>> filter, bool transient = false) : base(host, filter, transient)
- {
- Reset();
- }
- protected ListModel(IModelHost host, Func<Filter<TEntity>> filter, [NotNull] String filename) : base(host, filter, filename)
- {
- Reset();
- }
-
- protected override void Initialize()
- {
- _allitems = null;
- _items.Clear();
- }
- public virtual SortOrder<TEntity> Sort => LookupFactory.DefineSort<TEntity>();
-
- private IList<TItem> _allitems;
- private CoreTable _table = new CoreTable();
-
- private readonly CoreObservableCollection<TItem> _items = new CoreObservableCollection<TItem>();
-
- public IList<TItem> Items => _items;
- IEnumerable IListModel.Items => this.Items;
-
- public Func<TItem, bool> SearchPredicate { get; set; }
- public void Search(Func<TItem, bool> predicate)
- {
- SearchPredicate = predicate;
- Search();
- }
- public void Search()
- {
- _items.ReplaceRange(
- SearchPredicate != null
- ? new List<TItem>(_allitems.Where(SearchPredicate))
- : new List<TItem>(_allitems)
- );
- }
- protected virtual Expression<Func<TEntity, object>> ImageColumn => null;
-
- public override void BeforeLoad(MultiQuery query)
- {
-
- }
-
- public override void AfterLoad(MultiQuery query)
- {
-
- }
-
- public override IModel Refresh(bool force)
- {
- if (!Loaded || force)
- Load();
- return this;
- }
- public override void Refresh(bool force, Action loaded)
- {
- if (!Loaded || force)
- Load(loaded);
- else
- loaded?.Invoke();
- }
-
- public override void Load(Action loaded = null)
- {
- MultiQuery query = new MultiQuery();
-
- query.Add(
- Filter(),
- GetColumns<TItem,TEntity>(),
- Sort
- );
-
- if (ImageColumn != null)
- {
- query.Add<Document>(
- new Filter<Document>(x => x.ID).InQuery(Filter(), ImageColumn),
- new Columns<Document>(x => x.ID)
- .Add(x => x.Data)
- );
- }
-
- BeforeLoad(query);
- // If we have a valid transport, always try and get new data from the server
- if (Host.IsConnected())
- {
- if (loaded != null)
- query.Query((q) =>
- {
- if (Type == ModelType.Persistent)
- SaveToStorage(q);
- DoAfterLoad(q, loaded);
- });
- else
- {
- query.Query();
- if (Type == ModelType.Persistent)
- SaveToStorage(query);
- DoAfterLoad(query);
- }
- }
- else
- {
- if (Type == ModelType.Transient)
- {
- InitializeTables(query);
- }
- else if (Type == ModelType.Normal)
- {
- // Only load
- if (_allitems == null)
- InitializeTables(query);
- }
- else if (Type == ModelType.Persistent)
- {
- // Treat it as normal, unless its the first time through
- // in which case try to load it from storage, if the
- // data has been previously cached
- if (_allitems == null)
- LoadFromStorage(query);
- }
- DoAfterLoad(query, loaded);
- }
- }
-
- private void DoAfterLoad(MultiQuery query, Action loaded = null)
- {
- _table = query.Get<TEntity>();
- _allitems = new List<TItem>(query.Get<TEntity>().Rows.Select(row => CreateItem<TItem>(row)));
-
- if (ImageColumn != null)
- {
- Images.Clear();
- query.Get<Document>().IntoDictionary<Document, Guid, byte[]>(Images, x => x.ID,
- r => r.Get<Document, byte[]>(x => x.Data));
- }
- Search(null);
- AfterLoad(query);
- Loaded = true;
- loaded?.Invoke();
- NotifyChanged();
- }
- protected T CreateItem<T>(CoreRow row)
- where T : Shell<TParent,TEntity>, new()
- {
- var result = new T() { Row = row, Parent = (TParent)this };
- result.PropertyChanged += (sender, args) => DoPropertyChanged(result, args);
- return result;
- }
- public TItem CreateItem()
- {
- CoreRow row = _table.NewRow();
- var result = CreateItem<TItem>(row);
- return result;
- }
-
- public void CommitItem(TItem item)
- {
- _table.Rows.Add(item.Row);
- _allitems.Add(item);
- NotifyChanged();
- }
-
- public TItem AddItem()
- {
- var result = CreateItem();
- CommitItem(result);
- return result;
- }
-
- public void DeleteItem(TItem item)
- {
- _table.Rows.Remove(item.Row);
- _allitems.Remove(item);
- NotifyChanged();
- }
- object IListModel.CreateItem() => this.CreateItem();
-
- void IListModel.CommitItem(object item)
- {
- if (item is TItem titem)
- CommitItem(titem);
- }
-
- object IListModel.AddItem() => this.AddItem();
-
- void IListModel.DeleteItem(object item)
- {
- if (item is TItem titem)
- DeleteItem(titem);
- }
- IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator()
- {
- return Items.GetEnumerator();
- }
- public IEnumerator GetEnumerator()
- {
- return Items.GetEnumerator();
- }
- }
-
-
- }
|