Переглянути джерело

Implemented DateEditor Grid Column

frogsoftware 1 рік тому
батько
коміт
239f0ddcc5

+ 1 - 0
InABox.Core/Editors/DateEditor.cs

@@ -7,6 +7,7 @@
             Visible = Visible.Default;
             Width = 70;
             Alignment = Alignment.MiddleCenter;
+            Format = "dd/MM/yyyy";
             TodayVisible = false;
         }
 

+ 100 - 0
inabox.wpf/Behaviours/TextBox/TextBoxDateMaskBehavior.cs

@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Controls;
+using System.Windows.Input;
+using Microsoft.Xaml.Behaviors;
+
+namespace InABox.WPF;
+
+public class TextBoxDateMaskBehavior : Behavior<TextBox>
+{
+    private bool bFirst = true;
+    private List<Tuple<int, char>> _separators = new List<Tuple<int, char>>();
+    
+    private string _format = "";
+    public string Format
+    {
+        get => _format;
+        set
+        {
+            _format = value;
+            ReloadSeparators();
+        }
+    }
+    
+
+    private void ReloadSeparators()
+    {
+        _separators.Clear();
+        var formatted = String.Format("{0:"+_format+"}",DateTime.Today );
+        int iOffset = 0;
+        for (int i=0; i<formatted.Length; i++)
+        {
+            var ch = formatted[i];
+            if (!Char.IsNumber(ch))
+            {
+                _separators.Add(new Tuple<int, char>(i - iOffset, ch));
+                iOffset++;
+            }
+        }
+    }
+
+    public TextBoxDateMaskBehavior(string? format)
+    {
+        Format = String.IsNullOrWhiteSpace(format) 
+            ? "dd/MM/yyyy" 
+            : format;
+    }
+    
+    protected override void OnAttached()
+    {
+        AssociatedObject.PreviewTextInput += PreviewTextInput;
+        AssociatedObject.TextChanged += TextChanged;
+        AssociatedObject.MouseDoubleClick += MouseDoubleClick;
+        //AssociatedObject.GotFocus -= GotFocus;
+        //AssociatedObject.PreviewKeyDown -= PreviewKeyDown;
+        base.OnAttached();
+    }
+    
+    protected override void OnDetaching()
+    {
+        AssociatedObject.MouseDoubleClick -= MouseDoubleClick;
+        AssociatedObject.TextChanged -= TextChanged;
+        AssociatedObject.PreviewTextInput -= PreviewTextInput;
+        //AssociatedObject.GotFocus += GotFocus;
+        //AssociatedObject.PreviewKeyDown += PreviewKeyDown; 
+        base.OnDetaching();
+    }
+    
+    private void MouseDoubleClick(object sender, MouseButtonEventArgs e)
+    {
+        AssociatedObject.Text = String.Format("{0:" + Format + "}", DateTime.Now);
+    }
+
+    private void PreviewTextInput(object sender, TextCompositionEventArgs e)
+    {
+        bFirst = false;
+        if (!int.TryParse(e.Text, out int _))
+            e.Handled = true;
+    }
+
+    private void TextChanged(object sender, TextChangedEventArgs e)
+    {
+        var plaintext = AssociatedObject.Text?.Trim() ?? "";
+        foreach (var separator in _separators)
+            plaintext = plaintext.Replace(separator.Item2.ToString(), "");
+        
+        var decorated = plaintext;
+        for (int i = _separators.Count - 1; i >= 0; i--)
+        {
+            if (plaintext.Length >= _separators[i].Item1)
+                decorated = decorated.Insert(_separators[i].Item1, _separators[i].Item2.ToString());
+        }
+        AssociatedObject.Text = decorated;
+        if (bFirst)
+            AssociatedObject.SelectAll();
+        else
+            AssociatedObject.Select(AssociatedObject.Text.Length, 0);
+        e.Handled = true;
+    }
+}

+ 33 - 0
inabox.wpf/Converters/DateToStringConverter.cs

@@ -0,0 +1,33 @@
+using System;
+using System.Globalization;
+using InABox.Core;
+
+namespace InABox.WPF;
+
+public class DateToStringConverter : UtilityConverter<DateTime,String>
+{
+    public string Format { get; }
+        
+    public DateToStringConverter(string? format = null)
+    {
+        Format = format ?? "dd/MM/yyyy";
+    }
+    
+    public override string Convert(DateTime value)
+    {
+        if (value is DateTime datetime && !datetime.IsEmpty())
+            return String.Format("{0:" + Format + "}", datetime);
+        return "";
+    }
+
+    public override DateTime Deconvert(string value)
+    {
+        if (String.IsNullOrWhiteSpace(value))
+            return DateTime.MinValue;
+                
+        if (DateTime.TryParseExact(value, Format, CultureInfo.InvariantCulture, DateTimeStyles.None,
+                out DateTime result))
+            return result;
+        return DateTime.MinValue;
+    }
+}

+ 30 - 0
inabox.wpf/DynamicGrid/Columns/EditorColumns/DynamicGridDateColumn.cs

@@ -0,0 +1,30 @@
+using System.Windows.Controls;
+using System.Windows.Data;
+using InABox.Core;
+using InABox.WPF;
+using Microsoft.Xaml.Behaviors;
+
+namespace InABox.DynamicGrid;
+
+public class DynamicGridDateColumn<TEntity> : DynamicGridMaskColumn<TEntity,DateEditor> 
+    where TEntity : BaseObject
+{
+    protected override Behavior CreateBehaviour() => 
+        new TextBoxDateMaskBehavior(Definition?.Format);
+
+    protected override IValueConverter CreateConverter() =>
+        new DateToStringConverter(Definition?.Format);
+
+    protected override Button[] CreateButtons(TextBox textbox)
+    {
+        var button = new Button();
+        button.Content = "x";
+        button.Width = 25;
+        button.Click += (sender, args) => textbox.Text = "";
+        return new Button[] { button };
+    }
+
+    public DynamicGridDateColumn(DynamicGridColumn definition) : base(definition)
+    {
+    }
+}

+ 16 - 4
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -1735,6 +1735,8 @@ namespace InABox.DynamicGrid
                         newcol = new DynamicGridDoubleColumn<T>(column);
                     else if (prop.Editor is DateTimeEditor)
                         newcol = new DynamicGridDateTimeColumn<T>(column);
+                    else if (prop.Editor is DateEditor)
+                        newcol = new DynamicGridDateColumn<T>(column);
                     else if (prop.Editor is TimeOfDayEditor)
                         newcol = new DynamicGridTimeOfDayColumn<T>(column);
                     else if (prop.Editor is TimestampEditor)
@@ -2501,8 +2503,7 @@ namespace InABox.DynamicGrid
 
             if (IsDirectEditMode() && !OpenEditorOnDirectEdit)
             {
-                if (!CanCreateItems())
-                    return;
+ 
 
                 var item = CreateItem();
                 SaveItem(item);
@@ -2530,7 +2531,8 @@ namespace InABox.DynamicGrid
 
         private void Add_Click(object sender, RoutedEventArgs e)
         {
-            DoAdd();
+            if (CanCreateItems())
+                DoAdd();
         }
 
         public virtual DynamicEditorPages LoadEditorPages(T item)
@@ -2592,7 +2594,7 @@ namespace InABox.DynamicGrid
                 return result;
             };
 
-            editor.OnFormCustomiseEditor += (o, i, c, e) => OnCustomiseEditor?.Invoke(o, (T[])i, c, e);
+            editor.OnFormCustomiseEditor += DoCustomiseEditor;
 
             editor.OnDefineFilter = (type) => { return DefineFilter(type, items); };
 
@@ -2639,6 +2641,16 @@ namespace InABox.DynamicGrid
             AfterLoad(editor, items);
         }
 
+        private void DoCustomiseEditor(IDynamicEditorForm sender, object[] items, DynamicGridColumn column, BaseEditor editor)
+        {
+            CustomiseEditor((T[])items, column, editor);
+            OnCustomiseEditor?.Invoke(sender, (T[])items, column, editor);
+        }
+
+        protected virtual void CustomiseEditor(T[] items, DynamicGridColumn column, BaseEditor editor)
+        {
+        }
+
         protected virtual void DoAfterSave(IDynamicEditorForm editor, T[] items)
         {
             OnAfterSave?.Invoke(editor, items);