From 160a89ab7d990c2c02006a45fd3b62482cfcb381 Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Thu, 20 Aug 2020 14:09:15 -0700 Subject: [PATCH] Reuse WpfCellEventArgs when possible Fixes memory leaks with selected cells when the control is unloaded from the form. --- src/Eto.Wpf/Forms/Cells/CustomCellHandler.cs | 58 +++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/Eto.Wpf/Forms/Cells/CustomCellHandler.cs b/src/Eto.Wpf/Forms/Cells/CustomCellHandler.cs index 56c793e8fb..e609b83c1f 100755 --- a/src/Eto.Wpf/Forms/Cells/CustomCellHandler.cs +++ b/src/Eto.Wpf/Forms/Cells/CustomCellHandler.cs @@ -18,11 +18,6 @@ public class CustomCellHandler : CellHandler 0) { child = cache.Pop(); - if (child.Properties.ContainsKey(CellEventArgs_Key)) - { - args = child.Properties.Get(CellEventArgs_Key); - args.SetSelected(cell); - args.SetDataContext(wpfctl.DataContext); - } - else - child.Properties.Set(CellEventArgs_Key, args); + wpfctl.Control = child; + // get args for this control + args = GetEditArgs(handler, cell, wpfctl); } else { child = handler.Callback.OnCreateCell(handler.Widget, args); - child?.Properties.Set(CellEventArgs_Key, args); + wpfctl.Control = child; + // create args for this new control + args = GetEditArgs(handler, cell, wpfctl); + } + + if (!ReferenceEquals(args, originalArgs)) + { + args.SetSelected(cell); + args.SetRow(cell); + args.SetDataContext(wpfctl.DataContext); } + if (wpfctl.IsLoaded && child?.Loaded == false) { child.GetWpfFrameworkElement()?.SetScale(true, true); child.AttachNative(); } - wpfctl.Control = child; wpfctl.Identifier = id; wpfctl.Child = child.ToNative(); } - else - { - if (child.Properties.ContainsKey(CellEventArgs_Key)) - { - args = child.Properties.Get(CellEventArgs_Key); - args.SetSelected(cell); - args.SetDataContext(wpfctl.DataContext); - } - else - child.Properties.Set(CellEventArgs_Key, args); - } handler.Callback.OnConfigureCell(handler.Widget, args, child); handler.FormatCell(wpfctl, cell, wpfctl.DataContext); @@ -286,7 +276,8 @@ static void HandleControlUnloaded(object sender, sw.RoutedEventArgs e) { // Configure cell with null item to clear out data context and bindings. // Bindings can cause memory leaks if they are bounds to long lived objects. - var args = new WpfCellEventArgs(handler.ContainerHandler?.Grid, handler.Widget, -1, cell.Column, null, CellStates.None); + var args = GetEditArgs(handler, cell, wpfctl); + args.SetDataContext(null); handler.Callback.OnConfigureCell(handler.Widget, args, etoctl); } } @@ -343,12 +334,13 @@ static WpfCellEventArgs GetEditArgs(CustomCellHandler handler, swc.DataGridCell { if (handler == null) return null; - var ctl = editingElement as EtoBorder; - var args = ctl.Control.Properties.Get(CellEventArgs_Key); + var wpfctl = editingElement as EtoBorder; + var etoctl = wpfctl?.Control; + var args = etoctl?.Properties.Get(CellEventArgs_Key); if (args == null) { - args = new WpfCellEventArgs(handler.ContainerHandler?.Grid, handler.Widget, -1, cell.Column, ctl.DataContext, CellStates.None, ctl.Control); - ctl.Control.Properties.Set(CellEventArgs_Key, args); + args = new WpfCellEventArgs(handler.ContainerHandler?.Grid, handler.Widget, -1, cell.Column, wpfctl.IsLoaded ? wpfctl.DataContext : null, CellStates.None, etoctl); + etoctl?.Properties.Set(CellEventArgs_Key, args); } args.Handled = false; return args; @@ -401,4 +393,4 @@ public CustomCellHandler() } } -} \ No newline at end of file +}