Shell.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using System.Collections.Generic;
  2. using System.ComponentModel;
  3. using System.Runtime.CompilerServices;
  4. using InABox.Core;
  5. using Xamarin.Forms;
  6. namespace comal.timesheets
  7. {
  8. public abstract class Shell<TParent,TEntity> : BindableObject, INotifyPropertyChanged, IShell
  9. where TParent : IModel
  10. where TEntity : Entity
  11. {
  12. #region INotifyPropertyChanged
  13. public event PropertyChangedEventHandler PropertyChanged;
  14. protected void DoPropertyChanged(string propertyName)
  15. {
  16. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  17. }
  18. protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
  19. {
  20. if (EqualityComparer<T>.Default.Equals(field, value)) return false;
  21. field = value;
  22. DoPropertyChanged(propertyName);
  23. return true;
  24. }
  25. #endregion
  26. protected virtual void RowChanged()
  27. {
  28. }
  29. private CoreRow _row = null;
  30. public CoreRow Row
  31. {
  32. get => _row;
  33. set
  34. {
  35. _row = value;
  36. RowChanged();
  37. }
  38. }
  39. public TParent Parent { get; set; }
  40. IModel IShell.Parent => this.Parent;
  41. #region Row Get/Set Caching
  42. // We do this for three reasons:
  43. // 1. Rather than define properties in once class and columns in another,
  44. // we can define and link properties and columns in the one class,
  45. // using a _static_ constructor, which reduces complexity
  46. // 2. By caching based on the property name, we eliminate the need to convert
  47. // expressions to strings (expensive), while still retaining type-safety
  48. // 3. Using the Get/Set helper functions reduces code complexity when defining
  49. // shell properties, and distinguishes between data and calculated properties
  50. private static ShellColumns<TParent,TEntity> _columns = new ShellColumns<TParent,TEntity>();
  51. public static ShellColumns<TParent,TEntity> Columns
  52. {
  53. get { return _columns; }
  54. }
  55. protected virtual T Get<T>([CallerMemberName] string property = null)
  56. {
  57. var value = Row.Values[Columns.IndexOf(property)];
  58. return value != null ? (T)CoreUtils.ChangeType(value, typeof(T)) : CoreUtils.GetDefault<T>();
  59. }
  60. protected virtual void Set<T>(T value, bool notify = true, [CallerMemberName] string property = null)
  61. {
  62. Row.Values[Columns.IndexOf(property)] = value;
  63. if (notify)
  64. DoPropertyChanged(property);
  65. }
  66. #endregion
  67. }
  68. }