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

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();
             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
         #endregion
 
 
     }
     }

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

@@ -20,13 +20,13 @@ namespace InABox.DynamicGrid
 
 
         public ActionColumnToolTip? ToolTip { get; set; }
         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 string HeaderText { get; set; }
         public bool VerticalHeader { get; set; }
         public bool VerticalHeader { get; set; }
@@ -43,7 +43,7 @@ namespace InABox.DynamicGrid
             Position = DynamicActionColumnPosition.End;
             Position = DynamicActionColumnPosition.End;
         }
         }
 
 
-        public FrameworkElement? TextToolTip(string text)
+        public FrameworkElement? TextToolTip(string? text)
         {
         {
             if (string.IsNullOrWhiteSpace(text))
             if (string.IsNullOrWhiteSpace(text))
                 return null;
                 return null;
@@ -60,7 +60,7 @@ namespace InABox.DynamicGrid
             return border;
             return border;
         }
         }
 
 
-        public FrameworkElement? ImageToolTip(BitmapImage image)
+        public FrameworkElement? ImageToolTip(BitmapImage? image)
         {
         {
             if (image == null)
             if (image == null)
                 return null;
                 return null;
@@ -75,7 +75,7 @@ namespace InABox.DynamicGrid
             return result;
             return result;
         }
         }
 
 
-        public abstract object Data(CoreRow? row);
+        public abstract object? Data(CoreRow? row);
 
 
     }
     }
 
 
@@ -95,7 +95,7 @@ namespace InABox.DynamicGrid
             VerticalHeader = false;
             VerticalHeader = false;
         }
         }
 
 
-        public override object Data(CoreRow? row) => Text?.Invoke(row);
+        public override object? Data(CoreRow? row) => Text?.Invoke(row);
     }
     }
     
     
     public class DynamicImageColumn : DynamicActionColumn
     public class DynamicImageColumn : DynamicActionColumn
@@ -126,7 +126,7 @@ namespace InABox.DynamicGrid
             AllowHeaderClick = false;
             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;
             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 null;
             return _preview;
             return _preview;
         }
         }
 
 
-        protected Bitmap LoadBitmapFromDatabase(Guid imageid)
+        protected Bitmap? LoadBitmapFromDatabase(Guid imageid)
         {
         {
             if (imageid == Guid.Empty)
             if (imageid == Guid.Empty)
                 return null;
                 return null;
-            Bitmap result = null;
+            Bitmap? result = null;
             var image = new Client<Document>().Query(
             var image = new Client<Document>().Query(
                 new Filter<Document>(x => x.ID).IsEqualTo(imageid),
                 new Filter<Document>(x => x.ID).IsEqualTo(imageid),
                 new Columns<Document>(x => x.ID, x => x.Data)
                 new Columns<Document>(x => x.ID, x => x.Data)
@@ -61,9 +61,11 @@ namespace InABox.DynamicGrid
             return result;
             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);
             var imageid = arg.Get<Guid>(ImageIDProperty);
             if (!imageid.Equals(Guid.Empty))
             if (!imageid.Equals(Guid.Empty))
                 using (new WaitCursor())
                 using (new WaitCursor())
@@ -112,13 +114,13 @@ namespace InABox.DynamicGrid
             return item;
             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;
             var docid = id;
 
 
             if (bitmap != null && docid == Guid.Empty)
             if (bitmap != null && docid == Guid.Empty)
             {
             {
-                byte[] data = null;
+                byte[] data;
                 using (var ms = new MemoryStream())
                 using (var ms = new MemoryStream())
                 {
                 {
                     bitmap.Save(ms, ImageFormat.Png);
                     bitmap.Save(ms, ImageFormat.Png);
@@ -156,7 +158,7 @@ namespace InABox.DynamicGrid
             _parent.UpdateRow(row, _imagefilename, Path.GetFileName(filename));
             _parent.UpdateRow(row, _imagefilename, Path.GetFileName(filename));
         }
         }
 
 
-        private ContextMenu CreateImageMenu(CoreRow[] rows)
+        private ContextMenu? CreateImageMenu(CoreRow[]? rows)
         {
         {
             if (rows == null || rows.Length != 1)
             if (rows == null || rows.Length != 1)
                 return null;
                 return null;
@@ -194,7 +196,7 @@ namespace InABox.DynamicGrid
                 {
                 {
                     var filename = dlg.FileName.ToLower();
                     var filename = dlg.FileName.ToLower();
 
 
-                    Bitmap bmp = null;
+                    Bitmap bmp;
                     if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
                     if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
                     {
                     {
                         DxfUtils.OnProcessError += ((message) =>
                         DxfUtils.OnProcessError += ((message) =>
@@ -204,7 +206,7 @@ namespace InABox.DynamicGrid
                         bmp = DxfUtils.DXFToBitmap(filename);
                         bmp = DxfUtils.DXFToBitmap(filename);
                     }
                     }
                     else
                     else
-                        bmp = System.Drawing.Image.FromFile(filename) as Bitmap;
+                        bmp = (System.Drawing.Image.FromFile(filename) as Bitmap)!;
 
 
                     SaveBitmapToDatabase(row, Guid.Empty, filename, bmp);
                     SaveBitmapToDatabase(row, Guid.Empty, filename, bmp);
                     //_parent?.Refresh(false, false);
                     //_parent?.Refresh(false, false);
@@ -230,7 +232,7 @@ namespace InABox.DynamicGrid
         private void CopyImage(CoreRow row)
         private void CopyImage(CoreRow row)
         {
         {
             var bmp = LoadBitmapFromDatabase(row.Get<Guid>(ImageIDProperty));
             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<Guid>(ImageIDProperty),
                 row.Get<string>(_imagefilename),
                 row.Get<string>(_imagefilename),
                 bmp
                 bmp
@@ -247,26 +249,25 @@ namespace InABox.DynamicGrid
 
 
             var id = Guid.Empty;
             var id = Guid.Empty;
             var filename = "";
             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;
                 id = data.Item1;
                 filename = data.Item2;
                 filename = data.Item2;
                 bitmap = data.Item3;
                 bitmap = data.Item3;
             }
             }
             else if (Clipboard.ContainsImage())
             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);
                 filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now);
                 if (Clipboard.ContainsFileDropList())
                 if (Clipboard.ContainsFileDropList())
                 {
                 {
                     var list = Clipboard.GetFileDropList();
                     var list = Clipboard.GetFileDropList();
                     if (list.Count > 0)
                     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);
                 //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now);
@@ -274,7 +275,7 @@ namespace InABox.DynamicGrid
                 id = Guid.Empty;
                 id = Guid.Empty;
             }
             }
 
 
-            if (bitmap == null)
+            if (bitmap is null)
             {
             {
                 MessageBox.Show("Unable to paste data from clipboard");
                 MessageBox.Show("Unable to paste data from clipboard");
                 return;
                 return;

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

@@ -59,7 +59,7 @@ namespace InABox.DynamicGrid
             return item;
             return item;
         }
         }
 
 
-        private ContextMenu CreateIssuesMenu(CoreRow[] rows)
+        private ContextMenu? CreateIssuesMenu(CoreRow[]? rows)
         {
         {
             if (!Security.CanManageIssues<T>())
             if (!Security.CanManageIssues<T>())
                 return null;
                 return null;
@@ -82,6 +82,10 @@ namespace InABox.DynamicGrid
 
 
         private void ClearIssues(CoreRow[]? rows)
         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",
             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)
                     MessageBoxButton.YesNo) == MessageBoxResult.Yes)
             {
             {
@@ -102,8 +106,11 @@ namespace InABox.DynamicGrid
         private void EditIssues(CoreRow[]? rows)
         private void EditIssues(CoreRow[]? rows)
         {
         {
             var map = new Dictionary<CoreRow, T>();
             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)
             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();
                     var filter = e.FilterPredicates.Select(x => x.FilterValue.ToString()!).ToArray();
                     bool include = e.FilterPredicates.Any(x => x.FilterType == FilterType.Equals);
                     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
                 else
                     column.SelectedFilters = Array.Empty<string>();
                     column.SelectedFilters = Array.Empty<string>();
@@ -872,10 +872,9 @@ namespace InABox.DynamicGrid
         private void DataGrid_FilterItemsPopulating(object? sender, GridFilterItemsPopulatingEventArgs e)
         private void DataGrid_FilterItemsPopulating(object? sender, GridFilterItemsPopulatingEventArgs e)
         {
         {
             var col = DataGrid.Columns.IndexOf(e.Column);
             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
                 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)
         private CoreRow? GetRowFromIndex(int rowIndex)
@@ -1008,7 +1007,7 @@ namespace InABox.DynamicGrid
                 var colno = DataGridItems.Columns.IndexOf(mappedname);
                 var colno = DataGridItems.Columns.IndexOf(mappedname);
                 var corecol = Data.Columns[colno].ColumnName;
                 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 prefix = String.Join(".", corecol.Split(".").Reverse().Skip(1).Reverse());
                 var field = corecol.Split(".").Last();
                 var field = corecol.Split(".").Last();
@@ -1017,9 +1016,8 @@ namespace InABox.DynamicGrid
                 if (prop.GetEditor() is ILookupEditor editor)
                 if (prop.GetEditor() is ILookupEditor editor)
                 {
                 {
                     var data = editor.Values(corecol);
                     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)
                     foreach (CoreColumn lookupcol in data.Columns)
                     {
                     {
@@ -1083,7 +1081,7 @@ namespace InABox.DynamicGrid
                 row[$"ActionColumn{i}"] = ActionColumns[i].Data(corerow);
                 row[$"ActionColumn{i}"] = ActionColumns[i].Data(corerow);
         }
         }
 
 
-        private void UpdateData(Dictionary<CoreColumn,object> updates)
+        private void UpdateData(Dictionary<CoreColumn, object?> updates)
         {
         {
             if (!SelectedRows.Any())
             if (!SelectedRows.Any())
                 return;
                 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())
             if (!SelectedRows.Any())
                 return;
                 return;
@@ -1125,7 +1123,7 @@ namespace InABox.DynamicGrid
             if (DataGridItems is null || iRow > DataGridItems.Rows.Count)
             if (DataGridItems is null || iRow > DataGridItems.Rows.Count)
                 return;
                 return;
 
 
-            var updates = new Dictionary<CoreColumn, object>();
+            var updates = new Dictionary<CoreColumn, object?>();
             foreach (var key in changes.Keys)
             foreach (var key in changes.Keys)
             {
             {
                 var colno = DataGridItems.Columns.IndexOf(key);
                 var colno = DataGridItems.Columns.IndexOf(key);
@@ -1150,7 +1148,7 @@ namespace InABox.DynamicGrid
             var column = Data.Columns[colno];
             var column = Data.Columns[colno];
             var value = DataGridItems.Rows[iRow][mappedname];
             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)
         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)
             if (bOK && OnFilterRecord is not null)
                 bOK = OnFilterRecord(row);
                 bOK = OnFilterRecord(row);
             return bOK;
             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));
             Logger.Send(LogType.Information, "", string.Format("DynamicGridUtils.UpdateEditorValue({0},{1},{2})", items.Length, name, value));
             var sw = new Stopwatch();
             var sw = new Stopwatch();
@@ -423,7 +423,7 @@ namespace InABox.DynamicGrid
             return changes;
             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);
             var results = UpdateEditorValue(items, name, value);
             foreach (var key in results.Keys)
             foreach (var key in results.Keys)

+ 4 - 4
inabox.wpf/TemplateGenerator.cs

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