BaseDynamicGrid.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Imaging;
  11. using FastReport.Editor;
  12. using InABox.Core;
  13. using Syncfusion.Data;
  14. using static InABox.DynamicGrid.IDynamicGrid;
  15. using Selection = InABox.Core.Selection;
  16. namespace InABox.DynamicGrid
  17. {
  18. public abstract class BaseDynamicGrid : ContentControl
  19. {
  20. public static readonly DependencyProperty UseWaitCursorProperty =
  21. DependencyProperty.Register(nameof(UseWaitCursor), typeof(bool), typeof(BaseDynamicGrid));
  22. protected enum ClipAction
  23. {
  24. Cut,
  25. Copy
  26. }
  27. public BaseDynamicGrid()
  28. {
  29. UseWaitCursor = true;
  30. Options = new FluentList<DynamicGridOption>();
  31. }
  32. public bool UseWaitCursor
  33. {
  34. get => (bool)GetValue(UseWaitCursorProperty);
  35. set => SetValue(UseWaitCursorProperty, value);
  36. }
  37. public static Brush SelectionBackground { get; set; }
  38. public static Brush SelectionForeground { get; set; }
  39. public static Brush FilterBackground { get; set; }
  40. public FluentList<DynamicGridOption> Options { get; }
  41. public abstract void Reconfigure();
  42. public event IDynamicGrid.ReconfigureEvent? OnReconfigure;
  43. protected void OnReconfigureEvent(FluentList<DynamicGridOption> options)
  44. {
  45. OnReconfigure?.Invoke(options);
  46. }
  47. public virtual event OnCustomiseColumns? OnCustomiseColumns;
  48. protected void DoCustomiseColumnsEvent(object sender, DynamicGridColumns columns) =>
  49. OnCustomiseColumns?.Invoke(sender, columns);
  50. static BaseDynamicGrid()
  51. {
  52. SelectionForeground = new SolidColorBrush(Colors.Black);
  53. SelectionBackground = new SolidColorBrush(Colors.Silver);
  54. FilterBackground = new SolidColorBrush(Color.FromArgb(0xFF, 0xE9, 0xF7, 0xC9));
  55. }
  56. }
  57. public abstract class BaseDynamicGrid<T> : BaseDynamicGrid, IDynamicGrid where T : BaseObject, new()
  58. {
  59. public delegate void ValidateEvent(object sender, T[] items, List<string> errors);
  60. public event OnPrintData? OnPrintData;
  61. public event BeforeRefreshEventHandler? BeforeRefresh;
  62. protected void NotifyBeforeRefresh(BeforeRefreshEventArgs args) => BeforeRefresh?.Invoke(this, args);
  63. protected abstract bool OnBeforeRefresh();
  64. public event AfterRefreshEventHandler? AfterRefresh;
  65. protected void NotifyAfterRefresh(AfterRefreshEventArgs args) => AfterRefresh?.Invoke(this, args);
  66. protected abstract void OnAfterRefresh();
  67. public abstract event EntitySaveEvent? OnAfterSave;
  68. public abstract event EntitySaveEvent? OnBeforeSave;
  69. public event OnDefineFilter? OnDefineFilter;
  70. public abstract event OnFilterRecord? OnFilterRecord;
  71. public event OnCreateItem? OnCreateItem;
  72. public abstract event OnCustomiseEditor<T>? OnCustomiseEditor;
  73. public abstract event OnDoubleClick? OnDoubleClick;
  74. public OnGetDynamicGridRowStyle? OnGetRowStyle { get; set; }
  75. public ValidateEvent? OnValidate { get; set; }
  76. protected DynamicGridRowStyleSelector<T> RowStyleSelector;
  77. private bool _hasLoadedOptions = false;
  78. public BaseDynamicGrid()
  79. {
  80. Options.OnChanged += (sender, args) =>
  81. {
  82. _hasLoadedOptions = true;
  83. OptionsChanged();
  84. };
  85. RowStyleSelector = GetRowStyleSelector();
  86. RowStyleSelector.GetStyle += (row, style) => GetRowStyle(row, style);
  87. HiddenColumns = new HiddenColumnsList();
  88. }
  89. /// <summary>
  90. /// Initialise things like custom buttons; called once during construction.
  91. /// </summary>
  92. protected abstract void Init();
  93. protected abstract void DoReconfigure(FluentList<DynamicGridOption> options);
  94. /// <summary>
  95. /// Configure custom buttons and options.
  96. /// </summary>
  97. public void Reconfigure(FluentList<DynamicGridOption> options)
  98. {
  99. options.BeginUpdate().Clear();
  100. DoReconfigure(options);
  101. OnReconfigureEvent(options);
  102. options.EndUpdate();
  103. if (!_hasLoadedOptions)
  104. {
  105. _hasLoadedOptions = true;
  106. OptionsChanged();
  107. }
  108. }
  109. public override void Reconfigure()
  110. {
  111. Reconfigure(Options);
  112. }
  113. public void Reconfigure(ReconfigureEvent onReconfigure)
  114. {
  115. OnReconfigure += onReconfigure;
  116. Reconfigure();
  117. }
  118. public bool HasOption(DynamicGridOption option, IEnumerable<DynamicGridOption>? options = null) => (options ?? Options).Contains(option);
  119. bool IDynamicGrid.HasOption(InABox.DynamicGrid.DynamicGridOption option) => HasOption(option, null);
  120. public class HiddenColumnsList
  121. {
  122. private List<string> Columns { get; set; } = new();
  123. public IEnumerable<string> ColumnNames => Columns;
  124. public void Add(Expression<Func<T, object?>> column) => Add(CoreUtils.GetFullPropertyName(column, "."));
  125. public void Add(IColumn column) => Add(column.Property);
  126. public void Add(string column)
  127. {
  128. if (!Contains(column))
  129. Columns.Add(column);
  130. }
  131. public bool Contains(string column) => Columns.Contains(column);
  132. }
  133. public HiddenColumnsList HiddenColumns { get; }
  134. public void InitialiseEditorForm(IDynamicEditorForm editor, object[] items, Func<Type, CoreTable>? pageDataHandler = null, bool preloadPages = false)
  135. {
  136. InitialiseEditorForm(editor, items.Cast<T>().ToArray(), pageDataHandler, preloadPages);
  137. }
  138. public virtual bool EditItems(object[] items, Func<Type, CoreTable?>? PageDataHandler = null, bool PreloadPages = false)
  139. {
  140. var values = items.Cast<T>().ToArray();
  141. return EditItems(values, PageDataHandler, PreloadPages);
  142. }
  143. //public abstract bool DirectEdit(CoreTable data);
  144. public DynamicGridColumns MasterColumns { get; protected set; }
  145. public DynamicGridColumns VisibleColumns { get; protected set; }
  146. public CoreTable Data { get; set; }
  147. public virtual void ConfigureColumns(DynamicGridColumns columns)
  148. {
  149. DoCustomiseColumnsEvent(this,columns);
  150. }
  151. public abstract CoreRow[] SelectedRows { get; set; }
  152. public abstract void AddVisualFilter(string column, string value, FilterType filtertype = FilterType.Contains);
  153. public abstract Button AddButton(string? caption, BitmapImage? image, string? tooltip, DynamicGridButtonClickEvent action,
  154. DynamicGridButtonPosition position = DynamicGridButtonPosition.Left);
  155. public Button AddButton(string? caption, BitmapImage? image, DynamicGridButtonClickEvent action, DynamicGridButtonPosition position = DynamicGridButtonPosition.Left)
  156. {
  157. var result = AddButton(caption, image, null, action, position);
  158. return result;
  159. }
  160. public abstract void UpdateButton(Button button, BitmapImage? image, string? text, string? tooltip = null);
  161. public virtual double RowHeight { get; set; }
  162. public virtual double HeaderHeight { get; set; }
  163. public new virtual double FontSize { get; set; }
  164. public void AddHiddenColumn(string column) => HiddenColumns.Add(column);
  165. public abstract int DesiredWidth();
  166. public abstract void Refresh(bool reloadcolumns, bool reloaddata);
  167. public abstract void UpdateRow<TType>(CoreRow row, string column, TType value, bool refresh = true);
  168. public abstract void UpdateRow<TRow, TType>(CoreRow row, Expression<Func<TRow, TType>> column, TType value, bool refresh = true);
  169. protected abstract DynamicGridRowStyleSelector<T> GetRowStyleSelector();
  170. protected virtual DynamicGridStyle GetRowStyle(CoreRow row, DynamicGridStyle style)
  171. {
  172. return OnGetRowStyle != null ? OnGetRowStyle(row, style) : style;
  173. }
  174. public abstract void InitialiseEditorForm(IDynamicEditorForm editor, T[] items, Func<Type, CoreTable>? pageDataHandler = null, bool preloadPages = false);
  175. public abstract bool EditItems(T[] items, Func<Type, CoreTable?>? PageDataHandler = null, bool PreloadPages = false);
  176. public Filter<T>? DefineFilter()
  177. {
  178. if (OnDefineFilter is null)
  179. return null;
  180. var result = OnDefineFilter.Invoke(typeof(T)) as Filter<T>;
  181. return result;
  182. }
  183. protected virtual T CreateItem()
  184. {
  185. var result = new T();
  186. OnCreateItem?.Invoke(this, result);
  187. return result;
  188. }
  189. protected virtual void DoPrint(object sender)
  190. {
  191. OnPrintData?.Invoke(sender);
  192. }
  193. protected abstract void OptionsChanged();
  194. public IEnumerable<TType> ExtractValues<TType>(Expression<Func<T, TType>> column, Selection selection)
  195. {
  196. var result = selection == Selection.None
  197. ? Enumerable.Empty<TType>()
  198. : selection == Selection.Selected
  199. ? SelectedRows.Select(r => r.Get(column))
  200. : Data.ExtractValues(column);
  201. return result;
  202. }
  203. }
  204. }