Ver código fonte

Added BitmapImage.IsEqual() function
Tweaked BoolToVisibilityConverter and BoolToImageConverter
Fixed Update Events for DirectEdit Mode in DynamicGrid
Fixed DynamicGridCheckBox

frogsoftware 1 ano atrás
pai
commit
cfb8075a70

+ 12 - 13
inabox.wpf/Converters/BoolToVisibilityConverter.cs

@@ -1,25 +1,24 @@
 using System;
-using System.Collections.Generic;
 using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
-using System.Windows.Data;
 
-namespace InABox.Wpf;
+namespace InABox.WPF;
 
-public class BoolToVisibilityConverter : IValueConverter
+public class BoolToVisibilityConverter : UtilityConverter<bool,Visibility>
 {
-    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    public Visibility TrueValue { get; set; }
+    public Visibility FalseValue { get; set; }
+    
+    public override Visibility Convert(bool value)
     {
-        if (Equals(value, true))
-            return Visibility.Visible;
-        return Visibility.Collapsed;
+        return value
+            ? TrueValue
+            : FalseValue;
     }
 
-    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    public override bool Deconvert(Visibility value)
     {
-        throw new NotImplementedException();
+        return value == TrueValue;
     }
+    
 }

+ 80 - 11
inabox.wpf/DynamicGrid/Columns/EditorColumns/DynamicGridCheckBoxColumn.cs

@@ -1,9 +1,12 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls.Primitives;
 using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using InABox.Core;
 using InABox.WPF;
@@ -14,7 +17,8 @@ namespace InABox.DynamicGrid;
 public class DynamicGridCheckBoxColumn<TEntity> : DynamicGridEditorColumn<TEntity,CheckBoxEditor,GridTemplateColumn>
     where TEntity : BaseObject
 {
-    private readonly BitmapSource tick = Wpf.Resources.tick.AsBitmapImage();
+    private readonly BitmapImage ticked = Wpf.Resources.Bullet_Tick.AsBitmapImage();
+    private readonly BitmapImage unticked = null; //Wpf.Resources.tick.AsGrayScale().AsBitmapImage();
     
     protected override void Configure(GridTemplateColumn column, CheckBoxEditor editor)
     {
@@ -22,9 +26,15 @@ public class DynamicGridCheckBoxColumn<TEntity> : DynamicGridEditorColumn<TEntit
         (
             () =>
             {
-                var result = new Image() { Source = tick, Margin = new Thickness(2) };
-                var binding = new Binding() { Path = new PropertyPath(MappingName), Converter = new BooleanToVisibilityConverter() };
-                result.SetBinding(UIElement.VisibilityProperty, binding);
+                var result = new Image() { Margin = new Thickness(2) };
+                result.SetBinding(
+                    Image.SourceProperty, 
+                    new Binding()
+                    {
+                        Path = new PropertyPath(MappingName), 
+                        Converter = new BoolToImageConverter()
+                    }
+                );
                 return result;
             }
         );
@@ -33,17 +43,76 @@ public class DynamicGridCheckBoxColumn<TEntity> : DynamicGridEditorColumn<TEntit
         (
             () =>
             {
-                var result = new CheckBox() { IsThreeState = false };
-                var binding = new Binding() { Path = new PropertyPath(MappingName) };
-                result.SetBinding(ToggleButton.IsCheckedProperty, binding);
-                result.HorizontalAlignment = HorizontalAlignment.Center;
-                result.VerticalAlignment = VerticalAlignment.Center;
-                return result;
+                DockPanel dock = new DockPanel();
+                dock.Children.Add(CreateImage(ticked, Visibility.Visible, Visibility.Collapsed, BindingMode.TwoWay));
+                dock.Children.Add(CreateImage(unticked, Visibility.Collapsed, Visibility.Visible, BindingMode.TwoWay));
+                Border border = new Border()
+                {
+                    Background = new SolidColorBrush(Colors.White),
+                    Child = dock
+                };
+                
+                border.PreviewMouseDown += (sender, args) =>
+                {
+                    if (sender is Border b && b.Child is DockPanel d)
+                        ToggleImages(d);
+                    args.Handled = true;
+                };
+                border.KeyUp += (sender, args) =>
+                {
+                    if (args.Key == Key.Space && sender is Border b && b.Child is DockPanel d)
+                        ToggleImages(d);
+                    args.Handled = true;
+                };
+                return border;
             }
             
         );
         column.SetCellBoundValue = false;
- 
+    }
+
+    private static void ToggleImages(DockPanel d)
+    {
+        var t = d.Children.OfType<Image>().First();
+        var u = d.Children.OfType<Image>().Last();
+        t.Visibility = t.Visibility == Visibility.Visible
+            ? Visibility.Collapsed
+            : Visibility.Visible;
+        u.Visibility = u.Visibility == Visibility.Visible
+            ? Visibility.Collapsed
+            : Visibility.Visible;
+    }
+
+    private Image CreateImage(BitmapImage source, Visibility truevalue, Visibility falsevalue, BindingMode mode)
+    {
+        var image = new Image() { Source = source, Margin = new Thickness(2) };
+        image.SetValue(DockPanel.DockProperty,Dock.Top);
+        image.SetBinding(
+            Image.VisibilityProperty, 
+            new Binding()
+            {
+                Path = new PropertyPath(MappingName), 
+                Converter = new BoolToVisibilityConverter() { TrueValue = truevalue, FalseValue = falsevalue }, 
+                Mode = mode
+            }
+        );
+        image.PreviewMouseDown += (sender, args) =>
+        {
+            if (sender is Image i)
+                i.Visibility = i.Visibility == truevalue
+                    ? falsevalue
+                    : truevalue;
+            args.Handled = true;
+        };
+        image.KeyUp += (sender, args) =>
+        {
+            if (args.Key == Key.Space && sender is Image i)
+                i.Visibility = i.Visibility == truevalue
+                    ? falsevalue
+                    : truevalue;
+            args.Handled = true;
+        };
+        return image;
     }
 
     public override bool Filtered => false;

+ 7 - 2
inabox.wpf/DynamicGrid/Columns/EditorColumns/DynamicGridEditorColumn.cs

@@ -25,7 +25,12 @@ public abstract class DynamicGridEditorColumn<TEntity, TEditor, TColumn> : IDyna
     
     public Func<BaseObject>? GetEntity { get; set; }
     
-    public Action<Dictionary<string, object?>>? EntityChanged { get; set; }
+    public void DoEntityChanged(string columnname, Dictionary<string,object?> changes)
+    {
+        EntityChanged?.Invoke(this, new DynamicColumnEntityChangedEventArgs(columnname, changes));
+    }
+
+    public event DynamicColumnEntityChangedEvent EntityChanged;
 
     protected void UpdateData(Dictionary<string, object> updates)
     {
@@ -35,7 +40,7 @@ public abstract class DynamicGridEditorColumn<TEntity, TEditor, TColumn> : IDyna
             var changes = new Dictionary<string, object?>();
             foreach (var key in updates.Keys)
                 DynamicGridUtils.UpdateEditorValue(new BaseObject[] { entity }, key, updates[key], changes);
-            EntityChanged?.Invoke(changes);
+            EntityChanged?.Invoke(this, new DynamicColumnEntityChangedEventArgs(Definition.ColumnName, changes));
         }
     }
 

+ 26 - 0
inabox.wpf/DynamicGrid/Columns/EditorColumns/IDynamicColumnBase.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using NPOI.SS.Formula.Functions;
+
+namespace InABox.DynamicGrid;
+
+public class DynamicColumnEntityChangedEventArgs : EventArgs
+{
+    public string ColumnName { get; private set; }
+    
+    public Dictionary<string, object?> Changes { get; private set; }
+
+    public DynamicColumnEntityChangedEventArgs(string columnname, Dictionary<string, object?> changes)
+    {
+        ColumnName = columnname;
+        Changes = changes;
+    }
+}
+
+public delegate void DynamicColumnEntityChangedEvent(IDynamicColumnBase column, DynamicColumnEntityChangedEventArgs args);
+
+public interface IDynamicColumnBase
+{
+    void DoEntityChanged(String columnname, Dictionary<string, object?> changes);
+    event DynamicColumnEntityChangedEvent? EntityChanged;
+}

+ 2 - 2
inabox.wpf/DynamicGrid/Columns/EditorColumns/IDynamicGridEditorColumn.cs

@@ -5,7 +5,7 @@ using Syncfusion.UI.Xaml.Grid;
 
 namespace InABox.DynamicGrid;
 
-public interface IDynamicGridEditorColumn
+public interface IDynamicGridEditorColumn : IDynamicColumnBase
 {
     DynamicGridColumn? Definition { get; set; }
     string? MappingName { get; }
@@ -20,5 +20,5 @@ public interface IDynamicGridEditorColumn
     GridSummaryColumn? Summary();
 
     Func<BaseObject>? GetEntity { get; set; }
-    Action<Dictionary<string, object?>>? EntityChanged { get; set; }
+    
 }

+ 58 - 54
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -144,18 +144,25 @@ namespace InABox.DynamicGrid
 
     // Used to render boolean columns (the default "false" value shows what appears to be an intermediate state, which is ugly
     // This should show nothing for false, and a tick in a box for true
-    public class BoolToImageConverter : IValueConverter
+    public class BoolToImageConverter : UtilityConverter<bool,ImageSource>
     {
-        private static readonly BitmapImage tick = Wpf.Resources.Bullet_Tick.AsBitmapImage();
 
-        public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        public ImageSource TrueValue { get; set; }
+        public ImageSource FalseValue { get; set; }
+
+        public BoolToImageConverter()
+        {
+            TrueValue = Wpf.Resources.Bullet_Tick.AsBitmapImage();
+        }
+        
+        public override ImageSource Convert(bool value)
         {
-            return value is bool boolean && boolean ? tick : null;
+            return value ? TrueValue : FalseValue;
         }
 
-        public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        public override bool Deconvert(ImageSource value)
         {
-            return null;
+            return ImageUtils.IsEqual(value as BitmapImage,TrueValue as BitmapImage);
         }
     }
 
@@ -990,7 +997,7 @@ namespace InABox.DynamicGrid
             if (e.Column is GridCheckBoxColumn)
                 inplaceeditor = LoadItem(Data.Rows[e.RowColumnIndex.RowIndex - headerrows]);
             if (inplaceeditor is not null)
-                UpdateData(DataGrid.Columns[e.RowColumnIndex.ColumnIndex].MappingName);
+                UpdateData(e.RowColumnIndex.ColumnIndex);
             if (e.Column is GridCheckBoxColumn)
                 inplaceeditor = null;
             if (inplaceeditor is not null)
@@ -1035,7 +1042,8 @@ namespace InABox.DynamicGrid
                         if (updatecol != null)
                             updates[updatecol] = lookuprow[lookupcol.ColumnName];
                     }
-                    UpdateData(updates);
+                    var changes = UpdateData(updates);
+                    DoEntityChanged(this, new DynamicColumnEntityChangedEventArgs(corecol, changes));
                     bChanged = true;
                     
                 }
@@ -1068,8 +1076,10 @@ namespace InABox.DynamicGrid
             var headerrows = HasOption(DynamicGridOption.FilterRows) ? 2 : 1;
             if (e.RowColumnIndex.RowIndex < headerrows)
                 return;
-            if (inplaceeditor is not null && bChanged) 
-                UpdateData(DataGrid.Columns[e.RowColumnIndex.ColumnIndex].MappingName);
+            if (inplaceeditor is not null && bChanged)
+            {
+                UpdateData(e.RowColumnIndex.ColumnIndex);
+            }
             if (bChanged)
                 DoChanged();
             bChanged = false;
@@ -1094,26 +1104,26 @@ namespace InABox.DynamicGrid
                 row[$"ActionColumn{i}"] = ActionColumns[i].Data(corerow);
         }
 
-        private void UpdateData(Dictionary<CoreColumn, object?> updates)
+        private Dictionary<string,object?> UpdateData(Dictionary<CoreColumn, object?> updates)
         {
+            var result = new Dictionary<string, object?>();
             if (!SelectedRows.Any())
-                return;
+                return result;
 
             var iRow = SelectedRows.First().Index;
             var corerow = Data.Rows[iRow];
             var row = DataGridItems.Rows[iRow];
-
-            var changes = new Dictionary<string, object?>();
+            
             foreach (var (col, value) in updates)
             {
                 UpdateRow(corerow, col.ColumnName, value, refresh: false);
-                DynamicGridUtils.UpdateEditorValue(new BaseObject[] { inplaceeditor }, col.ColumnName, value, changes);
+                DynamicGridUtils.UpdateEditorValue(new BaseObject[] { inplaceeditor }, col.ColumnName, value, result);
             }
             
             SaveItem(inplaceeditor);
             
-            foreach (var key in changes.Keys)
-                UpdateCell(iRow, key, changes[key]);
+            foreach (var key in result.Keys)
+                UpdateCell(iRow, key, result[key]);
             
             // foreach (var c in Data.Columns.Where(x => !string.Equals(column.ColumnName, x.ColumnName)))
             // {
@@ -1124,49 +1134,41 @@ namespace InABox.DynamicGrid
             for (var i = 0; i < ActionColumns.Count; i++)
                 row[string.Format("ActionColumn{0}", i)] = ActionColumns[i].Data(corerow);
             
-        }
+            return result;
 
+        }
         
-        private void UpdateData(Dictionary<String, object?> changes)
+        private void UpdateData(int columnindex)
         {
+        
             if (!SelectedRows.Any())
                 return;
             
             var iRow = SelectedRows.First().Index; //e.RowColumnIndex.RowIndex - (HasOption(DynamicGridOptions.FilterRows) ? 2 : 1);
             if (DataGridItems is null || iRow > DataGridItems.Rows.Count)
                 return;
-
-            var updates = new Dictionary<CoreColumn, object?>();
-            foreach (var key in changes.Keys)
-            {
-                var colno = DataGridItems.Columns.IndexOf(key);
-                var column = Data.Columns[colno];
-                updates[column] = changes[key];
-            }
             
-            UpdateData(updates);
             
-        }
-        
-        private void UpdateData(String mappedname)
-        {
-            if (!SelectedRows.Any())
-                return;
-            
-            var iRow = SelectedRows.First().Index; //e.RowColumnIndex.RowIndex - (HasOption(DynamicGridOptions.FilterRows) ? 2 : 1);
-            if (DataGridItems is null || iRow > DataGridItems.Rows.Count)
-                return;
+            var gridcol = ColumnList[columnindex] as DynamicGridColumn;
 
-            var colno = DataGridItems.Columns.IndexOf(mappedname);
-            var column = Data.Columns[colno];
-            var value = DataGridItems.Rows[iRow][mappedname];
-            if(value is DBNull)
+            if (gridcol != null)
             {
-                value = CoreUtils.GetDefault(column.DataType);
+                var datacol = Data.Columns.FirstOrDefault(x => x.ColumnName.Equals(gridcol.ColumnName));
+                if (datacol != null)
+                {
+                    var datacolindex = Data.Columns.IndexOf(datacol);
+
+                //var colno = DataGridItems.Columns.IndexOf(mappedname);
+                //var column = Data.Columns.FirstOrDefault(x => x.ColumnName.Equals(gridcol.ColumnName));
+                //if (column != null)
+                //{
+                    var value = DataGridItems.Rows[iRow][datacolindex];
+                    if (value is DBNull)
+                        value = CoreUtils.GetDefault(datacol.DataType);
+                    var changes = UpdateData(new Dictionary<CoreColumn, object?>() { { datacol, value } });
+                    DoEntityChanged(gridcol, new DynamicColumnEntityChangedEventArgs(datacol.ColumnName,changes));
+                }
             }
-            
-            UpdateData(new Dictionary<CoreColumn, object?>() { { column, value } });
-            
         }
         
         private void DataGrid_QueryRowHeight(object? sender, QueryRowHeightEventArgs e)
@@ -1872,13 +1874,7 @@ namespace InABox.DynamicGrid
                     if (newcol != null)
                     {
                         newcol.GetEntity = () => inplaceeditor;
-                        newcol.EntityChanged = (changes) =>
-                        {
-                            SaveItem(inplaceeditor);
-                            UpdateRow(changes);
-                            DataGrid.SelectionController.CurrentCellManager.EndEdit();
-                        };
-                            
+                        newcol.EntityChanged += DoEntityChanged;
                         if (!newcol.VariableHeight)
                             gridRowResizingOptions.ExcludeColumns.Add(newcol.MappingName);
 
@@ -1985,7 +1981,15 @@ namespace InABox.DynamicGrid
             ResizeColumns(DataGrid, DataGrid.ActualWidth - 2, DataGrid.ActualHeight - 2);
         }
 
-        
+        private void DoEntityChanged(object column, DynamicColumnEntityChangedEventArgs args)
+        {
+
+            OnAfterEditorValueChanged(null, new T[] { inplaceeditor }, new AfterEditorValueChangedArgs(args.ColumnName, args.Changes), args.Changes);
+            SaveItem(inplaceeditor);
+            UpdateRow(args.Changes);
+            //DataGrid.SelectionController.CurrentCellManager.EndEdit();
+        }
+
 
         private void ApplyFilterStyle(GridColumn column, bool filtering, bool isactioncolumn)
         {

+ 8 - 1
inabox.wpf/DynamicGrid/DynamicGridCommon.cs

@@ -5,8 +5,15 @@ using InABox.Core;
 
 namespace InABox.DynamicGrid
 {
-    public abstract class DynamicColumnBase : BaseObject
+    
+    public abstract class DynamicColumnBase : BaseObject, IDynamicColumnBase
     {
+        public void DoEntityChanged(string columnname, Dictionary<string,object?> changes)
+        {
+            EntityChanged?.Invoke(this, new DynamicColumnEntityChangedEventArgs(columnname, changes));
+        }
+
+        public event DynamicColumnEntityChangedEvent? EntityChanged;
     }
 
     public enum DynamicGridOption

+ 1 - 1
inabox.wpf/Forms/Console/Console.xaml

@@ -4,7 +4,7 @@
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:InABox.Wpf.Console"
-		xmlns:wpf="clr-namespace:InABox.Wpf"
+		xmlns:wpf="clr-namespace:InABox.WPF"
         mc:Ignorable="d"
         x:Name="Window"
         DataContext="{Binding ElementName=Window}">

+ 2 - 3
inabox.wpf/Forms/ZoomPanel/ZoomPanel.xaml.cs

@@ -1,5 +1,4 @@
-using InABox.WPF;
-using java.security;
+using java.security;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -18,7 +17,7 @@ using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 
-namespace InABox.Wpf;
+namespace InABox.WPF;
 
 /// <summary>
 /// Interaction logic for ZoomPanel.xaml

+ 33 - 0
inabox.wpf/ImageUtils.cs

@@ -993,6 +993,39 @@ namespace InABox.WPF
                 return "ico";
             return "";
         }
+        
+        public static bool IsEqual(this BitmapImage? image1, BitmapImage? image2)
+        {
+            if (image1 == null || image2 == null)
+                return false;
+            return image1.ToBytes().SequenceEqual(image2.ToBytes());
+        }
+
+        public static byte[] ToBytes(this BitmapImage image)
+        {
+            byte[] data = new byte[] { };
+            if (image != null)
+            {
+                try
+                {
+                    var encoder = new BmpBitmapEncoder();
+                    encoder.Frames.Add(BitmapFrame.Create(image));
+                    using (MemoryStream ms = new MemoryStream())
+                    {
+                        encoder.Save(ms);
+                        data = ms.ToArray();
+                    }
+
+                    return data;
+                }
+                catch (Exception ex)
+                {
+                }
+            }
+
+            return data;
+        }
+
     }
 
 

+ 1 - 1
inabox.wpf/Themes/Generic.xaml

@@ -2,7 +2,7 @@
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:InABox.DynamicGrid"
-    xmlns:wpf="clr-namespace:InABox.Wpf"
+    xmlns:wpf="clr-namespace:InABox.WPF"
     xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
     xmlns:themes="clr-namespace:InABox.WPF.Themes"
     x:Class="InABox.WPF.Generic"