123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- using InABox.Core;
- using InABox.Wpf;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- namespace InABox.DynamicGrid
- {
- /// <summary>
- /// Interaction logic for EmbeddedDynamicEditorForm.xaml
- /// </summary>
- public partial class EmbeddedDynamicEditorForm : UserControl, IDynamicEditorForm
- {
- public event OnBeforeLoad? OnBeforeLoad;
- public void BeforeLoad() => OnBeforeLoad?.Invoke(this);
- public event OnAfterLoad? OnAfterLoad;
- public void AfterLoad() => OnAfterLoad?.Invoke(this);
- public event IDynamicEditorForm.OnReloadEventHandler? OnReload;
- public event EventHandler OnChanged;
- private bool bChanged = false;
- private bool _validated = false;
- public void DoChanged()
- {
- bChanged = true;
- _validated = false;
- //OKButton.IsEnabled = true;
- //CancelButton.IsEnabled = true;
- OnChanged?.Invoke(this, EventArgs.Empty);
- UpdateButtonEnabled();
- }
- public delegate void OKEvent();
- public delegate void CancelEvent();
- public DynamicEditorPages Pages { get; private set; } = [];
- private BaseObject[] _items;
- public BaseObject[] Items
- {
- get => _items;
- set
- {
- _items = value;
- DynamicEditorFormModel.Slug = Items?.FirstOrDefault()?.GetType().EntityName().Split('.').Last() ?? "";
- Editor.Load(Pages);
- bChanged = _items.Any(x => x is not Entity e || e.ID == Guid.Empty);
- UpdateButtonEnabled();
- foreach (var page in Pages)
- page.OnChanged += (sender, args) => DoChanged();
- }
- }
- public bool ReadOnly
- {
- get => Editor.ReadOnly;
- set
- {
- Editor.ReadOnly = value;
- UpdateButtonEnabled();
- }
- }
- private bool _disableIfUnchanged = false;
- public bool DisableOKIfUnchanged
- {
- get => _disableIfUnchanged;
- set
- {
- _disableIfUnchanged = value;
- UpdateButtonEnabled();
- }
- }
-
- private bool _hideButtons = false;
- public bool HideButtons
- {
- get => _hideButtons;
- set
- {
- _hideButtons = value;
- OKButton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
- CancelButton.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
- }
- }
- private bool _highlightButtons = false;
- public bool HighlightButtons
- {
- get => _highlightButtons;
- set
- {
- _highlightButtons = value;
- UpdateButtonHighlight(OKButton, Colors.DarkGreen, Colors.LimeGreen, Colors.White);
- UpdateButtonHighlight(CancelButton, Colors.Firebrick, Colors.Red, Colors.White);
- }
- }
- public double ContentWidth => Editor.TotalWidth;
- public double ContentHeight => Editor.TotalHeight;
- private void UpdateButtonEnabled()
- {
- OKButton.IsEnabled = !ReadOnly && (!DisableOKIfUnchanged || bChanged);
- CancelButton.IsEnabled = !ReadOnly;
- }
- private void UpdateButtonHighlight(Button button, Color border, Color background, Color foreground)
- {
- button.BorderBrush = _highlightButtons
- ? new SolidColorBrush(border)
- : new SolidColorBrush(Colors.Gray);
- button.Background = _highlightButtons
- ? new SolidColorBrush(background)
- : new SolidColorBrush(Colors.Gainsboro);
- button.Foreground = _highlightButtons
- ? new SolidColorBrush(foreground)
- : new SolidColorBrush(Colors.Black);
- button.FontWeight = _highlightButtons
- ? FontWeights.Bold
- : FontWeights.Normal;
- }
- public static readonly DependencyProperty ButtonsVisibleProperty =
- DependencyProperty.Register(
- nameof(ButtonsVisible),
- typeof(bool),
- typeof(EmbeddedDynamicEditorForm),
- new UIPropertyMetadata(true)
- );
-
- public bool ButtonsVisible
- {
- get => (bool)GetValue(ButtonsVisibleProperty);
- set
- {
- SetValue(ButtonsVisibleProperty, value);
- UpdateButtonsRowVisibility();
- }
- }
-
- private void UpdateButtonsRowVisibility()
- {
- ButtonRow.Height = ButtonsVisible
- ? new GridLength(1, GridUnitType.Auto)
- : new GridLength(0, GridUnitType.Pixel);
- }
-
- public static readonly DependencyProperty TabsVisibleProperty =
- DependencyProperty.Register(
- nameof(TabsVisible),
- typeof(bool),
- typeof(EmbeddedDynamicEditorForm),
- new UIPropertyMetadata(true)
- );
-
- public bool TabsVisible
- {
- get => (bool)GetValue(TabsVisibleProperty);
- set
- {
- SetValue(TabsVisibleProperty, value);
- UpdateTabsVisibility();
- }
- }
- private void UpdateTabsVisibility()
- {
- Editor.TabStripVisible = TabsVisible;
- }
- #region Events
- public event OnValidateData? OnValidateData;
- public OnCustomiseColumns? OnCustomiseColumns { get; set; }
- public OnDefineLookupFilter? OnDefineFilter { get; set; }
- public OnDefineLookup? OnDefineLookups { get; set; }
- public DefineEditorEventHandler? OnDefineEditor { get; set; }
- public event OnFormCustomiseEditor? OnFormCustomiseEditor;
- public OnReconfigureEditors? OnReconfigureEditors { get; set; }
- public event OnCreateEditorControl? OnCreateEditorControl;
- public event EditorValueChangedHandler? OnEditorValueChanged;
- public event OnAfterEditorValueChanged? OnAfterEditorValueChanged;
-
- public event OnSelectPage? OnSelectPage;
- public DynamicGridSaveEvent? OnSaveItem { get; set; }
- public DynamicEditorGrid.EditorCreatedHandler? OnEditorCreated;
- public event OKEvent? OnOK;
- public event CancelEvent? OnCancel;
- #endregion
- public EmbeddedDynamicEditorForm()
- {
- InitializeComponent();
- ReadOnly = false;
- Editor.Form = this;
- }
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- UpdateButtonsRowVisibility();
- UpdateTabsVisibility();
- }
- public EmbeddedDynamicEditorForm(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
- Func<Type, CoreTable>? PageDataHandler = null, bool PreloadPages = false): this()
- {
- Setup(type, pages, buttons, PageDataHandler, PreloadPages);
- }
- private IFilter? Editor_OnDefineFilter(Type type, string column)
- {
- return OnDefineFilter?.Invoke(type, column);
- }
- private void ClearEvents()
- {
- // These are events that are set by the grid/host.
- OnCreateEditorControl = null;
- OnEditorValueChanged = null;
- OnFormCustomiseEditor = null;
- OnAfterEditorValueChanged = null;
- OnSelectPage = null;
- OnValidateData = null;
- }
- public void Setup(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
- Func<Type, CoreTable?>? PageDataHandler = null, bool PreloadPages = false)
- {
- ClearEvents();
-
- Editor.UnderlyingType = type;
- Editor.OnLoadPage = page => { page.Load(Items.First(), PageDataHandler); };
- Editor.PreloadPages = PreloadPages;
- Pages = pages ?? new DynamicEditorPages();
- Buttons.Children.Clear();
- if (buttons != null)
- foreach (var button in buttons)
- {
- var btn = new Button();
- UpdateButton(btn, button.Image, button.Name);
- btn.Tag = button;
- btn.Margin = new Thickness(0, 0, 5, 0);
- btn.Padding = new Thickness(5, 0, 5, 0);
- btn.Click += Btn_Click;
- Buttons.Children.Add(btn);
- button.Button = btn;
- button.Form = this;
- }
- }
- public void UnloadEditorPages(bool saved)
- {
- Editor.UnloadPages(saved);
- }
- protected void UpdateButton(Button button, BitmapImage? image, string text)
- {
- var stackPnl = new StackPanel();
- stackPnl.Orientation = Orientation.Horizontal;
- //stackPnl.Margin = new Thickness(2);
- if (image != null)
- {
- var img = new Image();
- img.Source = image;
- img.Margin = new Thickness(2);
- stackPnl.Children.Add(img);
- }
- if (!string.IsNullOrEmpty(text))
- {
- var lbl = new Label();
- lbl.Content = text;
- lbl.VerticalAlignment = VerticalAlignment.Stretch;
- lbl.VerticalContentAlignment = VerticalAlignment.Center;
- lbl.Margin = new Thickness(2, 0, 5, 0);
- stackPnl.Children.Add(lbl);
- }
- button.Content = stackPnl;
- }
- private Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm sender, string name, object value)
- {
- if (OnEditorValueChanged != null)
- return OnEditorValueChanged(sender, name, value);
- return DynamicGridUtils.UpdateEditorValue(_items, name, value);
- }
- private void Editor_OnEditorCreated(object sender, double height, double width)
- {
- OnEditorCreated?.Invoke(sender, height, width);
- Editor.VerticalAlignment = VerticalAlignment.Stretch;
- Editor.HorizontalAlignment = HorizontalAlignment.Stretch;
- }
- private void Editor_OnCustomiseColumns(object sender, DynamicGridColumns columns)
- {
- columns.Clear();
- if (_items != null && _items.Any())
- columns.ExtractColumns(_items.First().GetType());
- OnCustomiseColumns?.Invoke(this, columns);
- }
- private void Btn_Click(object sender, RoutedEventArgs e)
- {
- var button = (Button)sender;
- var deb = (DynamicEditorButton)button.Tag;
- deb.Click();
- }
- public bool Validate()
- {
- var errors = OnValidateData?.Invoke(this, Items);
- if (errors != null && errors.Any())
- {
- MessageWindow.ShowMessage(
- string.Format("The following errors have been found with your data!\nPlease correct them and try again.\n\n- {0}",
- string.Join("\n- ", errors)),
- "Validation Error");
- return false;
- }
- _validated = true;
- return true;
- }
- private void OKButton_Click(object sender, RoutedEventArgs e)
- {
- if (!Validate())
- {
- return;
- }
- OnOK?.Invoke();
- //OKButton.IsEnabled = false;
- //CancelButton.IsEnabled = false;
- // Don't Commit the changes here, because we want to refer back to thos changes when we save the item
- // to trigger specific processes in the database
- //Close();
- }
- private void CancelButton_Click(object sender, RoutedEventArgs e)
- {
- // However, if we cancel the edits, then we can safely revert the items back to their original (loaded) state
- foreach (var item in _items)
- item.CancelChanges();
- foreach(var page in Editor.Pages)
- {
- page.Cancel();
- }
- OnCancel?.Invoke();
- //OKButton.IsEnabled = false;
- //CancelButton.IsEnabled = false;
- //Close();
- }
- public void SaveItem(CancelEventArgs e)
- {
- if(!_validated && !Validate())
- {
- e.Cancel = true;
- return;
- }
- OnSaveItem?.Invoke(this, e);
- _validated = false;
- }
- public bool TryFindEditor(string columnname, [NotNullWhen(true)] out IDynamicEditorControl? editor)
- {
- return Editor.TryFindEditor(columnname, out editor);
- }
- public object? GetEditorValue(string columnName) => this.FindEditor(columnName).GetValue(columnName);
- public void SetEditorValue(string columnName, object? value) => this.FindEditor(columnName).SetValue(columnName, value);
- public void SetLayoutType<T>() where T : DynamicEditorGridLayout => Editor.SetLayoutType<T>();
- public void SetLayoutType(Type t) => Editor.SetLayoutType(t);
- public void SetLayout(DynamicEditorGridLayout layout) => Editor.SetLayout(layout);
- private void Editor_OnSelectPage(DynamicEditorGrid sender, BaseObject[] items)
- {
- OnSelectPage?.Invoke(sender, items);
- }
- private void Editor_OnUnloadPage(IDynamicEditorPage page, bool saved)
- {
- if (!saved)
- page.BeforeSave(Items.First());
- else
- page.AfterSave(Items.First());
- }
- private Dictionary<string, object?>? Editor_OnAfterEditorValueChanged(DynamicEditorGrid sender, AfterEditorValueChangedArgs args)
- {
- if(args.ChangedValues.Count > 0)
- {
- DoChanged();
- }
- return OnAfterEditorValueChanged?.Invoke(sender, args);
- }
- private void Editor_OnReconfigureEditors(DynamicEditorGrid sender)
- {
- OnReconfigureEditors?.Invoke(sender);
- }
- private void Editor_OnGridCustomiseEditor(DynamicEditorGrid sender, DynamicGridColumn column, BaseEditor editor)
- {
- OnFormCustomiseEditor?.Invoke(this, Items, column, editor);
- }
- private decimal Editor_OnGetSequence(DynamicGridColumn column)
- {
- if (_items.Any())
- return CoreUtils.GetPropertySequence(_items.First().GetType(), column.ColumnName);
- return 0.0M;
- }
- private void Editor_OnDefineLookups(ILookupEditorControl editor)
- {
- OnDefineLookups?.Invoke(editor);
- }
- private BaseObject[] Editor_GetItems()
- {
- return _items;
- }
- private BaseEditor Editor_OnGetEditor(DynamicGridColumn column)
- {
- if (_items != null && _items.Any())
- {
- var property = DatabaseSchema.Property(Editor.UnderlyingType, column.ColumnName);
- if (property == null) return new NullEditor();
- if (property.Editor is NullEditor)
- return property.Editor.CloneEditor();
- BaseEditor editor;
- if (property is CustomProperty)
- {
- editor = property.Editor.CloneEditor();
- }
- else
- {
- editor = OnDefineEditor?.Invoke(_items[0], column) ?? column.Editor.CloneEditor();
- var propEditor = property.Editor;
- editor.Page = propEditor.Page;
- editor.Caption = propEditor.Caption;
- }
- //if (ReadOnly && editor.Editable.IsEditable())
- // editor.Editable = Editable.Disabled;
- return editor;
- }
- return new NullEditor();
- }
- private object? Editor_OnGetPropertyValue(object sender, string column)
- {
- if (!_items.Any())
- return null;
- object? result;
- try
- {
- result = CoreUtils.GetPropertyValue(_items.First(), column);
- }
- catch
- {
- result = _items.First().UserProperties.ContainsKey(column) ? _items.First().UserProperties[column] : null;
- }
- if (result == null)
- return null;
- foreach (var _item in _items)
- {
- object? curvalue;
- try
- {
- curvalue = CoreUtils.GetPropertyValue(_item, column);
- }
- catch
- {
- curvalue = _item.UserProperties.ContainsKey(column) ? _item.UserProperties[column] : null;
- }
- if (curvalue == null)
- return null;
- if (!curvalue.Equals(result))
- return null;
- }
- return result;
- }
- private void Editor_OnSetPropertyValue(object sender, string column, object value)
- {
- foreach (var _item in _items)
- if (_item.UserProperties.ContainsKey(column))
- _item.UserProperties[column] = value;
- else
- CoreUtils.SetPropertyValue(_item, column, value);
- }
- //public void EditLayout() => Editor.EditLayout();
- //public void ResetLayout() => Editor.ResetLayout();
- public void AddButton(Button button)
- {
- Buttons.Children.Add(button);
- }
- private Dictionary<string, object?> Editor_OnEditorValueChanged(DynamicEditorGrid sender, string name, object value)
- {
- return EditorValueChanged(this, name, value);
- }
- private void Editor_OnReload(DynamicEditorGrid sender)
- {
- OnReload?.Invoke(this);
- }
- private void Editor_OnCreateEditorControl(string column, BaseEditor editor, IDynamicEditorControl control)
- {
- OnCreateEditorControl?.Invoke(column, editor, control);
- }
- }
- }
|