From 12b053a33b873bc7e755550ed73cb965917583f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Cabanillas?= <76893296+Nicoo01x@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:57:05 -0300 Subject: [PATCH 1/2] Improvements to bad practices --- .../Project/Controls/DragListener.cs | 26 +++++++++++-- .../Project/OutlineView/OutlineNode.cs | 24 +++++++++++- .../Project/OutlineView/OutlineNodeBase.cs | 37 ++++++++++++++----- .../Project/Xaml/XamlModelProperty.cs | 18 +++++---- WpfDesign.XamlDom/Project/XamlObject.cs | 4 +- WpfDesign.XamlDom/Project/XamlParser.cs | 16 ++++++-- WpfDesign.XamlDom/Project/XamlProperty.cs | 6 ++- WpfDesign.XamlDom/Project/XamlPropertyInfo.cs | 9 +++-- 8 files changed, 107 insertions(+), 33 deletions(-) diff --git a/WpfDesign.Designer/Project/Controls/DragListener.cs b/WpfDesign.Designer/Project/Controls/DragListener.cs index a28f0c1..3b564eb 100644 --- a/WpfDesign.Designer/Project/Controls/DragListener.cs +++ b/WpfDesign.Designer/Project/Controls/DragListener.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls { public delegate void DragHandler(DragListener drag); - public class DragListener + public class DragListener : IDisposable { static DragListener() { @@ -33,15 +33,35 @@ static DragListener() } public Transform Transform { get; set; } - + + private bool _disposed; + public DragListener(IInputElement target) { Target = target; - + Target.PreviewMouseLeftButtonDown += Target_MouseDown; Target.PreviewMouseMove += Target_MouseMove; Target.PreviewMouseLeftButtonUp += Target_MouseUp; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) { + if (disposing && Target != null) { + Target.PreviewMouseLeftButtonDown -= Target_MouseDown; + Target.PreviewMouseMove -= Target_MouseMove; + Target.PreviewMouseLeftButtonUp -= Target_MouseUp; + } + _disposed = true; + } + } public void ExternalStart() { diff --git a/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs b/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs index ad9d883..4c16586 100644 --- a/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs +++ b/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs @@ -23,8 +23,10 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView { - public class OutlineNode: OutlineNodeBase + public class OutlineNode: OutlineNodeBase, IDisposable { + private bool _disposed; + protected OutlineNode(DesignItem designitem): base(designitem) { UpdateChildren(); @@ -35,6 +37,26 @@ protected OutlineNode(string name) : base(name) { } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) { + if (disposing) { + if (SelectionService != null) { + SelectionService.SelectionChanged -= Selection_SelectionChanged; + } + // Dispose base class event handlers + DisposeEventHandlers(); + } + _disposed = true; + } + } + static OutlineNode() { DummyPlacementType = PlacementType.Register("DummyPlacement"); diff --git a/WpfDesign.Designer/Project/OutlineView/OutlineNodeBase.cs b/WpfDesign.Designer/Project/OutlineView/OutlineNodeBase.cs index 5746e23..c271f25 100644 --- a/WpfDesign.Designer/Project/OutlineView/OutlineNodeBase.cs +++ b/WpfDesign.Designer/Project/OutlineView/OutlineNodeBase.cs @@ -57,8 +57,10 @@ protected OutlineNodeBase(DesignItem designItem) { hidden = object.Equals(designItem.Properties.GetAttachedProperty(DesignTimeProperties.IsHiddenProperty).GetConvertedValueOnInstance(), true); } - catch (Exception) - { } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to get IsHiddenProperty: {ex.Message}"); + } if (hidden) { _isDesignTimeVisible = false; } @@ -68,15 +70,15 @@ protected OutlineNodeBase(DesignItem designItem) { locked = object.Equals(designItem.Properties.GetAttachedProperty(DesignTimeProperties.IsLockedProperty).GetConvertedValueOnInstance(), true); } - catch (Exception) - { } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to get IsLockedProperty: {ex.Message}"); + } if (locked) { _isDesignTimeLocked = true; } - //TODO - - DesignItem.NameChanged += new EventHandler(DesignItem_NameChanged); + DesignItem.NameChanged += new EventHandler(DesignItem_NameChanged); if (DesignItem.ContentProperty != null && DesignItem.ContentProperty.IsCollection) { @@ -89,6 +91,21 @@ protected OutlineNodeBase(DesignItem designItem) } } + /// + /// Unsubscribes from DesignItem events to prevent memory leaks. + /// Called by derived classes during disposal. + /// + protected void DisposeEventHandlers() + { + if (DesignItem != null) { + DesignItem.NameChanged -= DesignItem_NameChanged; + DesignItem.PropertyChanged -= DesignItem_PropertyChanged; + if (DesignItem.ContentProperty != null && DesignItem.ContentProperty.IsCollection) { + DesignItem.ContentProperty.CollectionElements.CollectionChanged -= CollectionElements_CollectionChanged; + } + } + } + protected OutlineNodeBase(string name) { _name = name; @@ -96,9 +113,9 @@ protected OutlineNodeBase(string name) public DesignItem DesignItem { get; set; } - public virtual ServiceContainer Services - { - get { return this.DesignItem.Services; } + public virtual ServiceContainer Services + { + get { return this.DesignItem.Services; } } public ISelectionService SelectionService diff --git a/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs b/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs index 6cdcb8c..7a6216d 100644 --- a/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs +++ b/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs @@ -265,14 +265,14 @@ void ResetInternal() { if (_property.IsSet) { - var oldValue = _property.PropertyValue; + var oldValue = _property.PropertyValue; _property.Reset(); _designItem.NotifyPropertyChanged(this, oldValue, null); } - } - - public override T GetConvertedValueOnInstance() => _property.GetValueOnInstance(); - + } + + public override T GetConvertedValueOnInstance() => _property.GetValueOnInstance(); + public sealed class PropertyChangeAction : ITransactionItem { readonly XamlModelProperty property; @@ -331,11 +331,13 @@ public void Undo() else { if (property.DependencyProperty == null) { try - { + { property.SetValueOnInstance(oldValueOnInstance); } - catch(Exception) - { } + catch(Exception ex) + { + Debug.WriteLine($"SetValueOnInstance failed for {property.Name}: {ex.Message}"); + } } property.ResetInternal(); diff --git a/WpfDesign.XamlDom/Project/XamlObject.cs b/WpfDesign.XamlDom/Project/XamlObject.cs index 3c2d53c..7a137d0 100644 --- a/WpfDesign.XamlDom/Project/XamlObject.cs +++ b/WpfDesign.XamlDom/Project/XamlObject.cs @@ -696,7 +696,9 @@ BindingBase CopyBinding(BindingBase target) var val2 = pd.GetValue(target); if (object.Equals(val1, val2)) continue; pd.SetValue(b, val2); - } catch {} + } catch (Exception ex) { + Debug.WriteLine($"CopyBinding failed for property {pd.Name}: {ex.Message}"); + } } return b; diff --git a/WpfDesign.XamlDom/Project/XamlParser.cs b/WpfDesign.XamlDom/Project/XamlParser.cs index 2e6fa2b..6835bed 100644 --- a/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/WpfDesign.XamlDom/Project/XamlParser.cs @@ -626,8 +626,10 @@ internal static XamlPropertyInfo GetPropertyInfo(XamlTypeFinder typeFinder, obje { propertyInfo = FindProperty(elementInstance, propertyType, propertyName); } - catch (Exception) - { } + catch (Exception ex) + { + Debug.WriteLine($"FindProperty failed for {propertyType?.Name}.{propertyName}: {ex.Message}"); + } if (propertyInfo != null) return propertyInfo; } @@ -857,8 +859,14 @@ public static XamlObject ParseSnippet(XamlObject root, string xaml, XamlParserSe /// Returns the XamlObject of the parsed . public static XamlObject ParseSnippet(XamlObject root, string xaml, XamlParserSettings settings, XamlObject parentObject) { - XmlTextReader reader = new XmlTextReader(new StringReader(xaml)); - var element = root.OwnerDocument.XmlDocument.ReadNode(reader); + var readerSettings = new XmlReaderSettings { + DtdProcessing = DtdProcessing.Prohibit, + XmlResolver = null + }; + XmlNode element; + using (var reader = XmlReader.Create(new StringReader(xaml), readerSettings)) { + element = root.OwnerDocument.XmlDocument.ReadNode(reader); + } if (element != null) { XmlAttribute xmlnsAttribute=null; diff --git a/WpfDesign.XamlDom/Project/XamlProperty.cs b/WpfDesign.XamlDom/Project/XamlProperty.cs index 1f473ff..b9b4b18 100644 --- a/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -629,8 +629,10 @@ public object DesignerValue { return wr; } } - catch(Exception) - { } + catch(Exception ex) + { + Debug.WriteLine($"DesignerValue.GetValueFor failed for {propertyInfo?.Name}: {ex.Message}"); + } var value = propertyInfo.GetValue(parentObject.Instance); return value; } diff --git a/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs b/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs index a5b9a44..37695ac 100644 --- a/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs +++ b/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs @@ -116,8 +116,8 @@ public override object GetValue(object instance) if (attachedGetter != null) { return attachedGetter(instance); } - } catch (Exception) { - + } catch (Exception ex) { + Debug.WriteLine($"Attached property getter failed: {ex.Message}"); } var dependencyObject = instance as DependencyObject; @@ -175,8 +175,9 @@ public override void ResetValue(object instance) { try { _propertyDescriptor.ResetValue(instance); - } catch (Exception) { - //For Example "UndoRedoSimpleBinding" will raise a exception here => look if it has Side Effects if we generally catch here? + } catch (Exception ex) { + // For Example "UndoRedoSimpleBinding" will raise an exception here + Debug.WriteLine($"ResetValue failed for {_propertyDescriptor.Name}: {ex.Message}"); } } From f85c29e27bec1b1c91e70aa7808da64f878a476c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Cabanillas?= <76893296+Nicoo01x@users.noreply.github.com> Date: Mon, 2 Feb 2026 12:22:40 -0300 Subject: [PATCH 2/2] Update OutlineNode.cs --- .../Project/OutlineView/OutlineNode.cs | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs b/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs index 4c16586..b7a8ae4 100644 --- a/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs +++ b/WpfDesign.Designer/Project/OutlineView/OutlineNode.cs @@ -25,8 +25,6 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView { public class OutlineNode: OutlineNodeBase, IDisposable { - private bool _disposed; - protected OutlineNode(DesignItem designitem): base(designitem) { UpdateChildren(); @@ -37,24 +35,10 @@ protected OutlineNode(string name) : base(name) { } - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) + public virtual void Dispose() { - if (!_disposed) { - if (disposing) { - if (SelectionService != null) { - SelectionService.SelectionChanged -= Selection_SelectionChanged; - } - // Dispose base class event handlers - DisposeEventHandlers(); - } - _disposed = true; - } + SelectionService.SelectionChanged -= Selection_SelectionChanged; + DisposeEventHandlers(); } static OutlineNode()