Просмотр исходного кода

Fix null exception issues with columns

Kenric Nugteren 1 год назад
Родитель
Сommit
7b0523bf36

+ 18 - 0
InABox.Core/CoreUtils.cs

@@ -2739,6 +2739,24 @@ namespace InABox.Core
             yield return fnc();
         }
 
+        public static (List<T>, List<T>) PartitionToList<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
+        {
+            var trueResult = new List<T>();
+            var falseResult = new List<T>();
+            foreach(var item in enumerable)
+            {
+                if (predicate(item))
+                {
+                    trueResult.Add(item);
+                }
+                else
+                {
+                    falseResult.Add(item);
+                }
+            }
+            return (trueResult, falseResult);
+        }
+
         #endregion
 
     }

+ 10 - 10
inabox.wpf/DynamicGrid/Columns/DynamicActionColumn.cs

@@ -20,13 +20,13 @@ namespace InABox.DynamicGrid
 
         public ActionColumnToolTip? ToolTip { get; set; }
         
-        public string[] SelectedFilters { get; set; }
-        public string[] Filters { get; set; }
-        public Func<CoreRow, string[], bool> FilterRecord { get; set; }
+        public string[]? SelectedFilters { get; set; }
+        public string[]? Filters { get; set; }
+        public Func<CoreRow, string[], bool>? FilterRecord { get; set; }
 
-        public Func<CoreRow[], ContextMenu> ContextMenu { get; set; }
+        public Func<CoreRow[]?, ContextMenu?>? ContextMenu { get; set; }
 
-        public object Tag { get; set; }
+        public object? Tag { get; set; }
 
         public string HeaderText { get; set; }
         public bool VerticalHeader { get; set; }
@@ -43,7 +43,7 @@ namespace InABox.DynamicGrid
             Position = DynamicActionColumnPosition.End;
         }
 
-        public FrameworkElement? TextToolTip(string text)
+        public FrameworkElement? TextToolTip(string? text)
         {
             if (string.IsNullOrWhiteSpace(text))
                 return null;
@@ -60,7 +60,7 @@ namespace InABox.DynamicGrid
             return border;
         }
 
-        public FrameworkElement? ImageToolTip(BitmapImage image)
+        public FrameworkElement? ImageToolTip(BitmapImage? image)
         {
             if (image == null)
                 return null;
@@ -75,7 +75,7 @@ namespace InABox.DynamicGrid
             return result;
         }
 
-        public abstract object Data(CoreRow? row);
+        public abstract object? Data(CoreRow? row);
 
     }
 
@@ -95,7 +95,7 @@ namespace InABox.DynamicGrid
             VerticalHeader = false;
         }
 
-        public override object Data(CoreRow? row) => Text?.Invoke(row);
+        public override object? Data(CoreRow? row) => Text?.Invoke(row);
     }
     
     public class DynamicImageColumn : DynamicActionColumn
@@ -126,7 +126,7 @@ namespace InABox.DynamicGrid
             AllowHeaderClick = false;
         }
         
-        public override object Data(CoreRow? row) => Image?.Invoke(row);
+        public override object? Data(CoreRow? row) => Image?.Invoke(row);
     }
     
 }

+ 20 - 19
inabox.wpf/DynamicGrid/Columns/DynamicImageManagerColumn.cs

@@ -36,18 +36,18 @@ namespace InABox.DynamicGrid
             ToolTip = CreateImageToolTip;
         }
 
-        private static BitmapImage PreviewImage(CoreRow arg)
+        private static BitmapImage? PreviewImage(CoreRow? arg)
         {
-            if (arg == null || arg.Get<Guid>(ImageIDProperty) == Guid.Empty)
+            if (arg is null || arg.Get<Guid>(ImageIDProperty) == Guid.Empty)
                 return null;
             return _preview;
         }
 
-        protected Bitmap LoadBitmapFromDatabase(Guid imageid)
+        protected Bitmap? LoadBitmapFromDatabase(Guid imageid)
         {
             if (imageid == Guid.Empty)
                 return null;
-            Bitmap result = null;
+            Bitmap? result = null;
             var image = new Client<Document>().Query(
                 new Filter<Document>(x => x.ID).IsEqualTo(imageid),
                 new Columns<Document>(x => x.ID, x => x.Data)
@@ -61,9 +61,11 @@ namespace InABox.DynamicGrid
             return result;
         }
 
-        private FrameworkElement CreateImageToolTip(DynamicActionColumn column, CoreRow arg)
+        private FrameworkElement? CreateImageToolTip(DynamicActionColumn column, CoreRow? arg)
         {
-            FrameworkElement result = null;
+            if (arg is null)
+                return null;
+            FrameworkElement? result = null;
             var imageid = arg.Get<Guid>(ImageIDProperty);
             if (!imageid.Equals(Guid.Empty))
                 using (new WaitCursor())
@@ -112,13 +114,13 @@ namespace InABox.DynamicGrid
             return item;
         }
 
-        private void SaveBitmapToDatabase(CoreRow row, Guid id, string filename, Bitmap bitmap)
+        private void SaveBitmapToDatabase(CoreRow row, Guid id, string filename, Bitmap? bitmap)
         {
             var docid = id;
 
             if (bitmap != null && docid == Guid.Empty)
             {
-                byte[] data = null;
+                byte[] data;
                 using (var ms = new MemoryStream())
                 {
                     bitmap.Save(ms, ImageFormat.Png);
@@ -156,7 +158,7 @@ namespace InABox.DynamicGrid
             _parent.UpdateRow(row, _imagefilename, Path.GetFileName(filename));
         }
 
-        private ContextMenu CreateImageMenu(CoreRow[] rows)
+        private ContextMenu? CreateImageMenu(CoreRow[]? rows)
         {
             if (rows == null || rows.Length != 1)
                 return null;
@@ -194,7 +196,7 @@ namespace InABox.DynamicGrid
                 {
                     var filename = dlg.FileName.ToLower();
 
-                    Bitmap bmp = null;
+                    Bitmap bmp;
                     if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
                     {
                         DxfUtils.OnProcessError += ((message) =>
@@ -204,7 +206,7 @@ namespace InABox.DynamicGrid
                         bmp = DxfUtils.DXFToBitmap(filename);
                     }
                     else
-                        bmp = System.Drawing.Image.FromFile(filename) as Bitmap;
+                        bmp = (System.Drawing.Image.FromFile(filename) as Bitmap)!;
 
                     SaveBitmapToDatabase(row, Guid.Empty, filename, bmp);
                     //_parent?.Refresh(false, false);
@@ -230,7 +232,7 @@ namespace InABox.DynamicGrid
         private void CopyImage(CoreRow row)
         {
             var bmp = LoadBitmapFromDatabase(row.Get<Guid>(ImageIDProperty));
-            var data = new Tuple<Guid, string, Bitmap>(
+            var data = new Tuple<Guid, string, Bitmap?>(
                 row.Get<Guid>(ImageIDProperty),
                 row.Get<string>(_imagefilename),
                 bmp
@@ -247,26 +249,25 @@ namespace InABox.DynamicGrid
 
             var id = Guid.Empty;
             var filename = "";
-            Bitmap bitmap = null;
+            Bitmap? bitmap = null;
 
-            if (Clipboard.ContainsData("ProductImage"))
+            if (Clipboard.ContainsData("ProductImage") && Clipboard.GetData("ProductImage") is Tuple<Guid, string, Bitmap?> data)
             {
-                var data = Clipboard.GetData("ProductImage") as Tuple<Guid, string, Bitmap>;
                 id = data.Item1;
                 filename = data.Item2;
                 bitmap = data.Item3;
             }
             else if (Clipboard.ContainsImage())
             {
-                var data = Clipboard.GetImage();
-                bitmap = data.AsBitmap2();
+                var dataImage = Clipboard.GetImage();
+                bitmap = dataImage.AsBitmap2();
 
                 filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now);
                 if (Clipboard.ContainsFileDropList())
                 {
                     var list = Clipboard.GetFileDropList();
                     if (list.Count > 0)
-                        filename = Path.ChangeExtension(Path.GetFileName(list[0]), ".png");
+                        filename = Path.ChangeExtension(Path.GetFileName(list[0]!), ".png");
                 }
 
                 //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now);
@@ -274,7 +275,7 @@ namespace InABox.DynamicGrid
                 id = Guid.Empty;
             }
 
-            if (bitmap == null)
+            if (bitmap is null)
             {
                 MessageBox.Show("Unable to paste data from clipboard");
                 return;

+ 10 - 3
inabox.wpf/DynamicGrid/Columns/DynamicIssuesColumn.cs

@@ -59,7 +59,7 @@ namespace InABox.DynamicGrid
             return item;
         }
 
-        private ContextMenu CreateIssuesMenu(CoreRow[] rows)
+        private ContextMenu? CreateIssuesMenu(CoreRow[]? rows)
         {
             if (!Security.CanManageIssues<T>())
                 return null;
@@ -82,6 +82,10 @@ namespace InABox.DynamicGrid
 
         private void ClearIssues(CoreRow[]? rows)
         {
+            if(rows is null)
+            {
+                return;
+            }
             if (MessageBox.Show("This will clear the flagged issues for these items!\n\nAre you sure you wish to continue?", "Confirm",
                     MessageBoxButton.YesNo) == MessageBoxResult.Yes)
             {
@@ -102,8 +106,11 @@ namespace InABox.DynamicGrid
         private void EditIssues(CoreRow[]? rows)
         {
             var map = new Dictionary<CoreRow, T>();
-            foreach (var row in rows)
-                map[row] = row.ToObject<T>();
+            if(rows is not null)
+            {
+                foreach (var row in rows)
+                    map[row] = row.ToObject<T>();
+            }
 
             if (new DynamicIssuesEditor(map.Values.ToArray()).ShowDialog() == true)
             {

+ 15 - 15
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -844,7 +844,7 @@ namespace InABox.DynamicGrid
                 {
                     var filter = e.FilterPredicates.Select(x => x.FilterValue.ToString()!).ToArray();
                     bool include = e.FilterPredicates.Any(x => x.FilterType == FilterType.Equals);
-                    column.SelectedFilters = include ? filter : column.Filters.Except(filter).ToArray();
+                    column.SelectedFilters = include ? filter : (column.Filters ?? Enumerable.Empty<string>()).Except(filter).ToArray();
                 }
                 else
                     column.SelectedFilters = Array.Empty<string>();
@@ -872,10 +872,9 @@ namespace InABox.DynamicGrid
         private void DataGrid_FilterItemsPopulating(object? sender, GridFilterItemsPopulatingEventArgs e)
         {
             var col = DataGrid.Columns.IndexOf(e.Column);
-            var column = ColumnList[col] as DynamicActionColumn;
-            if (column != null)
+            if (ColumnList[col] is DynamicActionColumn column && column.Filters is not null)
                 e.ItemsSource = column.Filters.Select(x => new FilterElement
-                { DisplayText = x, ActualValue = x, IsSelected = column.SelectedFilters == null || column.SelectedFilters.Contains(x) });
+                { DisplayText = x, ActualValue = x, IsSelected = column.SelectedFilters is null || column.SelectedFilters.Contains(x) });
         }
 
         private CoreRow? GetRowFromIndex(int rowIndex)
@@ -1008,7 +1007,7 @@ namespace InABox.DynamicGrid
                 var colno = DataGridItems.Columns.IndexOf(mappedname);
                 var corecol = Data.Columns[colno].ColumnName;
 
-                Dictionary<CoreColumn, object> updates = new Dictionary<CoreColumn, object>();
+                var updates = new Dictionary<CoreColumn, object?>();
 
                 var prefix = String.Join(".", corecol.Split(".").Reverse().Skip(1).Reverse());
                 var field = corecol.Split(".").Last();
@@ -1017,9 +1016,8 @@ namespace InABox.DynamicGrid
                 if (prop.GetEditor() is ILookupEditor editor)
                 {
                     var data = editor.Values(corecol);
-                    var lookuprow = data.Rows.FirstOrDefault(r => Equals(r[field], tuple.Item1));
-                    if (lookuprow == null)
-                        lookuprow = data.NewRow(true);
+                    var lookuprow = data.Rows.FirstOrDefault(r => Equals(r[field], tuple.Item1))
+                        ?? data.NewRow(true);
 
                     foreach (CoreColumn lookupcol in data.Columns)
                     {
@@ -1083,7 +1081,7 @@ namespace InABox.DynamicGrid
                 row[$"ActionColumn{i}"] = ActionColumns[i].Data(corerow);
         }
 
-        private void UpdateData(Dictionary<CoreColumn,object> updates)
+        private void UpdateData(Dictionary<CoreColumn, object?> updates)
         {
             if (!SelectedRows.Any())
                 return;
@@ -1116,7 +1114,7 @@ namespace InABox.DynamicGrid
         }
 
         
-        private void UpdateData(Dictionary<String,object> changes)
+        private void UpdateData(Dictionary<String, object?> changes)
         {
             if (!SelectedRows.Any())
                 return;
@@ -1125,7 +1123,7 @@ namespace InABox.DynamicGrid
             if (DataGridItems is null || iRow > DataGridItems.Rows.Count)
                 return;
 
-            var updates = new Dictionary<CoreColumn, object>();
+            var updates = new Dictionary<CoreColumn, object?>();
             foreach (var key in changes.Keys)
             {
                 var colno = DataGridItems.Columns.IndexOf(key);
@@ -1150,7 +1148,7 @@ namespace InABox.DynamicGrid
             var column = Data.Columns[colno];
             var value = DataGridItems.Rows[iRow][mappedname];
             
-            UpdateData(new Dictionary<CoreColumn, object>() { { column, value } });
+            UpdateData(new Dictionary<CoreColumn, object?>() { { column, value } });
             
         }
         
@@ -1920,9 +1918,11 @@ namespace InABox.DynamicGrid
 
         protected virtual bool FilterRecord(CoreRow row)
         {
-            var bOK = true;
-            foreach (var column in ActionColumns.Where(x => x.FilterRecord != null && x.SelectedFilters != null && x.SelectedFilters.Any()))
-                bOK = bOK && column.FilterRecord.Invoke(row, column.SelectedFilters);
+            var bOK = ActionColumns.All(x =>
+            {
+                return x.FilterRecord is null || x.SelectedFilters is null || !x.SelectedFilters.Any()
+                    || x.FilterRecord.Invoke(row, x.SelectedFilters);
+            });
             if (bOK && OnFilterRecord is not null)
                 bOK = OnFilterRecord(row);
             return bOK;

+ 2 - 2
inabox.wpf/DynamicGrid/DynamicGridUtils.cs

@@ -368,7 +368,7 @@ namespace InABox.DynamicGrid
 
 
 
-        public static Dictionary<string, object?> UpdateEditorValue(BaseObject[] items, string name, object value)
+        public static Dictionary<string, object?> UpdateEditorValue(BaseObject[] items, string name, object? value)
         {
             Logger.Send(LogType.Information, "", string.Format("DynamicGridUtils.UpdateEditorValue({0},{1},{2})", items.Length, name, value));
             var sw = new Stopwatch();
@@ -423,7 +423,7 @@ namespace InABox.DynamicGrid
             return changes;
         }
 
-        public static void UpdateEditorValue(BaseObject[] items, string name, object value, Dictionary<string, object?> changes)
+        public static void UpdateEditorValue(BaseObject[] items, string name, object? value, Dictionary<string, object?> changes)
         {
             var results = UpdateEditorValue(items, name, value);
             foreach (var key in results.Keys)

+ 4 - 4
inabox.wpf/TemplateGenerator.cs

@@ -9,7 +9,7 @@ namespace InABox.WPF
         /// <summary>
         ///     Creates a data-template that uses the given delegate to create new instances.
         /// </summary>
-        public static DataTemplate CreateDataTemplate(Func<object> factory)
+        public static DataTemplate CreateDataTemplate(Func<object?> factory)
         {
             if (factory == null)
                 throw new ArgumentNullException("factory");
@@ -25,7 +25,7 @@ namespace InABox.WPF
         /// <summary>
         ///     Creates a control-template that uses the given delegate to create new instances.
         /// </summary>
-        public static ControlTemplate CreateControlTemplate(Type controlType, Func<object> factory)
+        public static ControlTemplate CreateControlTemplate(Type controlType, Func<object?> factory)
         {
             if (controlType == null)
                 throw new ArgumentNullException("controlType");
@@ -44,13 +44,13 @@ namespace InABox.WPF
         private sealed class _TemplateGeneratorControl :
             ContentControl
         {
-            internal static readonly DependencyProperty FactoryProperty = DependencyProperty.Register("Factory", typeof(Func<object>),
+            internal static readonly DependencyProperty FactoryProperty = DependencyProperty.Register("Factory", typeof(Func<object?>),
                 typeof(_TemplateGeneratorControl), new PropertyMetadata(null, _FactoryChanged));
 
             private static void _FactoryChanged(DependencyObject instance, DependencyPropertyChangedEventArgs args)
             {
                 var control = (_TemplateGeneratorControl)instance;
-                var factory = (Func<object>)args.NewValue;
+                var factory = (Func<object?>)args.NewValue;
                 if (factory != null)
                     control.Content = factory();
             }