[mapguide-commits] r8017 - in trunk/Tools/Maestro: Maestro.Base/Editor Maestro.Base/Events Maestro.Base/Services Maestro.Base/UI Maestro.Editors Maestro.Editors/FeatureSource Maestro.Editors/FeatureSource/Extensions Maestro.Editors/Fusion Maestro.Editors/LayerDefinition Maestro.Editors/LayerDefinition/Drawing Maestro.Editors/LayerDefinition/Raster Maestro.Editors/LayerDefinition/Vector Maestro.Editors/LayerDefinition/Vector/GridEditor Maestro.Editors/LayerDefinition/Vector/Scales Maestro.Editors/LoadProcedure Maestro.Editors/MapDefinition Maestro.Editors/SymbolDefinition Maestro.Editors/WebLayout Maestro.Editors/WebLayout/Commands Maestro.Shared.UI OSGeo.MapGuide.MaestroAPI

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed Apr 9 04:16:33 PDT 2014


Author: jng
Date: 2014-04-09 04:16:33 -0700 (Wed, 09 Apr 2014)
New Revision: 8017

Added:
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/WeakEventHandler.cs
Modified:
   trunk/Tools/Maestro/Maestro.Base/Editor/EditorContentBase.cs
   trunk/Tools/Maestro/Maestro.Base/Editor/ResourceEditorService.cs
   trunk/Tools/Maestro/Maestro.Base/Events/EventWatcher.cs
   trunk/Tools/Maestro/Maestro.Base/Services/OpenResourceManager.cs
   trunk/Tools/Maestro/Maestro.Base/Services/ServerConnectionManager.cs
   trunk/Tools/Maestro/Maestro.Base/UI/BroadcastTextWriter.cs
   trunk/Tools/Maestro/Maestro.Base/UI/ISiteExplorer.cs
   trunk/Tools/Maestro/Maestro.Base/UI/MessageViewer.cs
   trunk/Tools/Maestro/Maestro.Base/UI/OutboundRequestViewer.cs
   trunk/Tools/Maestro/Maestro.Base/UI/ResourceIdNavigator.cs
   trunk/Tools/Maestro/Maestro.Base/UI/ResourcePropertiesDialog.Designer.cs
   trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs
   trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs
   trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs
   trunk/Tools/Maestro/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/Fusion/MapSettingsCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetManagementDialog.cs
   trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetSettingsCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Drawing/DrawingLayerSettingsCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/LayerPropertiesSectionCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Raster/RasterLayerSettingsSectionCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/GridEditor/VectorScaleRangeGrid.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/Scales/SymbolInstancesDialog.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/LoadProcedure/LoadTargetCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapLayersSectionCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapTreeModels.cs
   trunk/Tools/Maestro/Maestro.Editors/ResourceEditorServiceBase.cs
   trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/CompoundSymbolDefinitionEditorCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/SymbolField.cs
   trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/InvokeURLCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/SearchCmdCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/WebLayout/MenuEditorCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/WebLayout/WebLayoutSettingsCtrl.cs
   trunk/Tools/Maestro/Maestro.Shared.UI/ViewContentManagerBase.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
Log:
#2319: Use weak events to avoid resource leaks due to object being kept alive by their registered event handlers. This submission doesn't plug all of these leaks, but the majority of the prime offenders (INotifyPropertyChanged handlers) have been moved to use weak events.

To allow for the use of weak events for some of our existing events,their event handler delegate signatures have been modified to use the standard (object sender, SomeClassDerivedFromEventArgs e) format.

Modified: trunk/Tools/Maestro/Maestro.Base/Editor/EditorContentBase.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Editor/EditorContentBase.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/Editor/EditorContentBase.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -100,13 +100,14 @@
 
                 _svc = value;
                 _svc.PreviewLocale = PropertyService.Get(ConfigProperties.PreviewLocale, ConfigProperties.DefaultPreviewLocale);
-                _svc.DirtyStateChanged += OnDirtyStateChanged;
-                _svc.Saved += OnSaved;
-                _svc.BeforeSave += OnBeforeSave;
+                _svc.DirtyStateChanged += WeakEventHandler.Wrap(OnDirtyStateChanged, (eh) => _svc.DirtyStateChanged -= eh);
+                _svc.Saved += WeakEventHandler.Wrap(OnSaved, (eh) => _svc.Saved -= eh);
+                _svc.BeforeSave += WeakEventHandler.Wrap<CancelEventHandler>(OnBeforeSave, (eh) => _svc.BeforeSave -= eh);
 
                 {
                     var res = _svc.GetEditedResource();
-                    res.CurrentConnection.SessionIDChanged += OnSessionIdChanged;
+                    var conn = res.CurrentConnection;
+                    conn.SessionIDChanged += WeakEventHandler.Wrap(OnSessionIdChanged, (eh) => conn.SessionIDChanged -= eh);
                 }
 
                 UpdateTitle();

Modified: trunk/Tools/Maestro/Maestro.Base/Editor/ResourceEditorService.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Editor/ResourceEditorService.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/Editor/ResourceEditorService.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -53,7 +53,7 @@
         internal void ReReadSessionResource()
         {
             _editCopy = _conn.ResourceService.GetResource(this.EditedResourceID);
-            _editCopy.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(OnResourcePropertyChanged);
+            _editCopy.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnResourcePropertyChanged, (eh) => _editCopy.PropertyChanged -= eh);
         }
 
         public override void OpenUrl(string url)

Modified: trunk/Tools/Maestro/Maestro.Base/Events/EventWatcher.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Events/EventWatcher.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/Events/EventWatcher.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -115,7 +115,7 @@
             }
         }
 
-        static void OnConnectionRemoved(object sender, string name)
+        static void OnConnectionRemoved(object sender, ServerConnectionEventArgs e)
         {
             Workbench wb = Workbench.Instance;
             Debug.Assert(wb.ActiveSiteExplorer != null);
@@ -124,7 +124,7 @@
             //Debug.Assert(wb.ActiveSiteExplorer.ConnectionName == name);
         }
 
-        static void OnConnectionAdded(object sender, string name)
+        static void OnConnectionAdded(object sender, ServerConnectionEventArgs e)
         {
             var wb = Workbench.Instance;
             if (wb.ActiveSiteExplorer == null)
@@ -146,11 +146,11 @@
                 wb.AddToolbar("Resource ID Bar", nav.NavigatorToolStrip, ToolbarRegion.Top, true);
             }
 
-            wb.ActiveSiteExplorer.RefreshModel(name);
+            wb.ActiveSiteExplorer.RefreshModel(e.ConnectionName);
             
 
             var svc = ServiceRegistry.GetService<ServerConnectionManager>();
-            var conn = svc.GetConnection(name);
+            var conn = svc.GetConnection(e.ConnectionName);
 
             LoggingService.Info("There are now " + svc.GetConnectionNames().Count + " active connections"); //NOXLATE
         }

Modified: trunk/Tools/Maestro/Maestro.Base/Services/OpenResourceManager.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Services/OpenResourceManager.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/Services/OpenResourceManager.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -26,6 +26,7 @@
 using Maestro.Base.Editor;
 using OSGeo.MapGuide.MaestroAPI.Resource;
 using Maestro.Shared.UI;
+using System.ComponentModel;
 
 namespace Maestro.Base.Services
 {
@@ -190,7 +191,7 @@
                 var editorSvc = new ResourceEditorService(res.ResourceID, conn, launcher, siteExp, this);
                 ed.EditorService = editorSvc;
                 _openItems[key] = ed;
-                ed.ViewContentClosing += (sender, e) =>
+                CancelEventHandler vcClosing = (sender, e) =>
                 {
                     if (ed.IsDirty && !ed.DiscardChangesOnClose)
                     {
@@ -213,13 +214,15 @@
                         }
                     }
                 };
-                ed.ViewContentClosed += (sender, e) =>
+                ed.ViewContentClosing += WeakEventHandler.Wrap<CancelEventHandler>(vcClosing, (eh) => ed.ViewContentClosing -= eh);
+                EventHandler vcClosed = (sender, e) =>
                 {
                     //Recompute the resource key as that may have changed by a save as operation
                     _openItems.Remove(ComputeResourceKey(((EditorContentBase)sender).EditorService.ResourceID, conn));
                     siteExp.FlagNode(conn.DisplayName, ed.EditorService.ResourceID, NodeFlagAction.None);
                 };
-                ed.EditorService.Saved += (sender, e) =>
+                ed.ViewContentClosed += WeakEventHandler.Wrap(vcClosed, (eh) => ed.ViewContentClosed -= eh);
+                EventHandler edSaved = (sender, e) =>
                 {
                     //If saved from new resource, the resource id would be session based
                     //So we need to update this to the new resource id as defined by the
@@ -231,10 +234,12 @@
                         _openItems[ComputeResourceKey(ed.EditorService.ResourceID, conn)] = ed2;
                     }
                 };
-                ed.DirtyStateChanged += (sender, e) =>
+                ed.EditorService.Saved += WeakEventHandler.Wrap(edSaved, (eh) => ed.EditorService.Saved -= eh);
+                EventHandler dirty = (sender, e) =>
                 {
                     siteExp.FlagNode(conn.DisplayName, res.ResourceID, ed.IsDirty ? NodeFlagAction.HighlightDirty : NodeFlagAction.HighlightOpen);
                 };
+                ed.DirtyStateChanged += WeakEventHandler.Wrap(dirty, (eh) => ed.DirtyStateChanged -= eh);
             }
             _openItems[key].Activate();
             siteExp.FlagNode(conn.DisplayName, res.ResourceID, _openItems[key].IsDirty ? NodeFlagAction.HighlightDirty : NodeFlagAction.HighlightOpen);

Modified: trunk/Tools/Maestro/Maestro.Base/Services/ServerConnectionManager.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/Services/ServerConnectionManager.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/Services/ServerConnectionManager.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -31,8 +31,8 @@
     /// Defines a method for connection-related events
     /// </summary>
     /// <param name="sender"></param>
-    /// <param name="name"></param>
-    public delegate void ServerConnectionEventHandler(object sender, string name);
+    /// <param name="e"></param>
+    public delegate void ServerConnectionEventHandler(object sender, ServerConnectionEventArgs e);
     /// <summary>
     /// Defines a method that handles connection pre-removal
     /// </summary>
@@ -61,6 +61,23 @@
         public string ConnectionName { get; set; }
     }
 
+    public class ServerConnectionEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the ServerConnectionEventArgs class
+        /// </summary>
+        /// <param name="name"></param>
+        public ServerConnectionEventArgs(string name)
+        {
+            this.ConnectionName = name;
+        }
+
+        /// <summary>
+        /// Gets the name of the connection that is about to be closed
+        /// </summary>
+        public string ConnectionName { get; set; }
+    }
+
     /// <summary>
     /// Manages <see cref="T:OSGeo.MapGuide.MaestroAPI.IServerConnection"/> instances
     /// </summary>
@@ -124,7 +141,7 @@
             _connections.Add(name, conn);
             var handler = this.ConnectionAdded;
             if (handler != null)
-                handler(this, name);
+                handler(this, new ServerConnectionEventArgs(name));
         }
 
         /// <summary>
@@ -149,7 +166,7 @@
 
                 var removed = this.ConnectionRemoved;
                 if (removed != null)
-                    removed(this, name);
+                    removed(this, new ServerConnectionEventArgs(name));
                 return conn;
             }
             return null;

Modified: trunk/Tools/Maestro/Maestro.Base/UI/BroadcastTextWriter.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/BroadcastTextWriter.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/BroadcastTextWriter.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -29,7 +29,7 @@
     /// </summary>
     /// <param name="sender"></param>
     /// <param name="msg"></param>
-    public delegate void LogBroadcastEventHandler(object sender, LogMessage msg);
+    public delegate void LogBroadcastEventHandler(object sender, LogMessageEventArgs msg);
 
     /// <summary>
     /// A TextWriter that broadcasts all messages written to it
@@ -60,7 +60,7 @@
         /// </summary>
         public event LogBroadcastEventHandler LogMessage;
 
-        private List<LogMessage> _buffered = new List<LogMessage>();
+        private List<LogMessageEventArgs> _buffered = new List<LogMessageEventArgs>();
 
         /// <summary>
         /// Flushes any buffered messages
@@ -105,7 +105,7 @@
         /// <param name="value"></param>
         public override void Write(string value)
         {
-            var message = new LogMessage() { LogDate = DateTime.Now, Message = value };
+            var message = new LogMessageEventArgs() { LogDate = DateTime.Now, Message = value };
             var handler = this.LogMessage;
             if (handler != null)
             {
@@ -153,7 +153,7 @@
     /// <summary>
     /// An application log message
     /// </summary>
-    public class LogMessage
+    public class LogMessageEventArgs : EventArgs
     {
         /// <summary>
         /// Gets or sets the log date

Modified: trunk/Tools/Maestro/Maestro.Base/UI/ISiteExplorer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/ISiteExplorer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/ISiteExplorer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -97,12 +97,22 @@
         event RepositoryItemEventHandler ItemsSelected;
     }
 
+    public class RepositoryItemEventArgs : EventArgs
+    {
+        public RepositoryItemEventArgs(RepositoryItem[] items)
+        {
+            this.Items = items;
+        }
+
+        public RepositoryItem[] Items { get; private set; }
+    }
+
     /// <summary>
     /// Defines a method to handle item selection in the Site Explorer
     /// </summary>
     /// <param name="sender"></param>
-    /// <param name="items"></param>
-    public delegate void RepositoryItemEventHandler(object sender, RepositoryItem[] items);
+    /// <param name="e"></param>
+    public delegate void RepositoryItemEventHandler(object sender, RepositoryItemEventArgs e);
 
     /// <summary>
     /// Defines a set of possible actions that can be performed on nodes in the Site Explorer

Modified: trunk/Tools/Maestro/Maestro.Base/UI/MessageViewer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/MessageViewer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/MessageViewer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -27,6 +27,7 @@
 using ICSharpCode.Core;
 using System.IO;
 using Maestro.Shared.UI;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Base.UI
 {
@@ -46,11 +47,11 @@
             base.OnLoad(e);
             
             var btw = BroadcastTextWriter.Instance;
-            btw.LogMessage += new LogBroadcastEventHandler(OnLogMessage);
+            btw.LogMessage += WeakEventHandler.Wrap<LogBroadcastEventHandler>(OnLogMessage, (eh) => btw.LogMessage -= eh);
             btw.FlushMessages();
         }
 
-        void OnLogMessage(object sender, LogMessage msg)
+        void OnLogMessage(object sender, LogMessageEventArgs msg)
         {
             if (!txtMessages.IsDisposed)
             {

Modified: trunk/Tools/Maestro/Maestro.Base/UI/OutboundRequestViewer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/OutboundRequestViewer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/OutboundRequestViewer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -46,7 +46,7 @@
                 var connMgr = ServiceRegistry.GetService<ServerConnectionManager>();
                 connMgr.ConnectionAdded += (s, args) =>
                 {
-                    var conn = connMgr.GetConnection(args);
+                    var conn = connMgr.GetConnection(args.ConnectionName);
                     conn.RequestDispatched += OnRequestDispatched;
                 };
                 connMgr.ConnectionRemoving += (s, ce) =>

Modified: trunk/Tools/Maestro/Maestro.Base/UI/ResourceIdNavigator.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/ResourceIdNavigator.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/ResourceIdNavigator.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -20,6 +20,7 @@
 using ICSharpCode.Core;
 using Maestro.Base.Editor;
 using Maestro.Base.Services;
+using Maestro.Shared.UI;
 using OSGeo.MapGuide.MaestroAPI;
 using OSGeo.MapGuide.MaestroAPI.Resource;
 using System;
@@ -57,32 +58,32 @@
                                    ISiteExplorer siteExp)
         {
             _connMgr = connMgr;
-            _connMgr.ConnectionAdded += OnConnectionAdded;
-            _connMgr.ConnectionRemoved += OnConnectionRemoved;
+            _connMgr.ConnectionAdded += WeakEventHandler.Wrap<ServerConnectionEventHandler>(OnConnectionAdded, (eh) => _connMgr.ConnectionAdded -= eh);
+            _connMgr.ConnectionRemoved += WeakEventHandler.Wrap<ServerConnectionEventHandler>(OnConnectionRemoved, (eh) => _connMgr.ConnectionRemoved -= eh);
 
             _omgr = omgr;
             _viewMgr = viewMgr;
-            _viewMgr.ViewActivated += OnViewActivated;
+            _viewMgr.ViewActivated += WeakEventHandler.Wrap<Maestro.Shared.UI.ViewEventHandler>(OnViewActivated, (eh) => _viewMgr.ViewActivated -= eh);
 
             _siteExp = siteExp;
-            _siteExp.ItemsSelected += OnSiteExplorerItemsSelected;
+            _siteExp.ItemsSelected += WeakEventHandler.Wrap<RepositoryItemEventHandler>(OnSiteExplorerItemsSelected, (eh) => _siteExp.ItemsSelected -= eh);
 
             _strip = new ToolStrip();
-            _strip.Layout += OnToolStripLayout;
+            _strip.Layout += WeakEventHandler.Wrap<LayoutEventHandler>(OnToolStripLayout, (eh) => _strip.Layout -= eh);
             _strip.Stretch = true;
 
             _resIdLabel = new ToolStripLabel(Strings.Label_ResourceID);
             _cmbResourceId = new ToolStripComboBox();
             _cmbResourceId.AutoSize = false;
             _cmbResourceId.Width = 250;
-            _cmbResourceId.TextChanged += OnResourceIdChanged;
-            _cmbResourceId.KeyUp += OnResourceIdKeyUp;
+            _cmbResourceId.TextChanged += WeakEventHandler.Wrap(OnResourceIdChanged, (eh) => _cmbResourceId.TextChanged -= eh);
+            _cmbResourceId.KeyUp += WeakEventHandler.Wrap<KeyEventHandler>(OnResourceIdKeyUp, (eh) => _cmbResourceId.KeyUp -= eh);
 
             _atLabel = new ToolStripLabel("@"); //NOXLATE
             _cmbActiveConnections = new ToolStripComboBox();
             _cmbActiveConnections.AutoSize = false;
             _cmbActiveConnections.Width = 250;
-            _cmbActiveConnections.ComboBox.SelectedIndexChanged += OnActiveConnectionChanged;
+            _cmbActiveConnections.ComboBox.SelectedIndexChanged += WeakEventHandler.Wrap(OnActiveConnectionChanged, (eh) => _cmbActiveConnections.ComboBox.SelectedIndexChanged -= eh);
             _cmbActiveConnections.ComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
 
             _btnGo = new ToolStripButton(Strings.Label_Open);
@@ -90,14 +91,14 @@
             _btnGo.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
             _btnGo.TextImageRelation = TextImageRelation.TextBeforeImage;
             _btnGo.ToolTipText = Strings.Label_OpenResource;
-            _btnGo.Click += btnGo_Click;
+            _btnGo.Click += WeakEventHandler.Wrap(btnGo_Click, (eh) => _btnGo.Click -= eh);
 
             _btnOpenAsXml = new ToolStripButton(Strings.Label_OpenAsXml);
             _btnOpenAsXml.Image = Properties.Resources.arrow;
             _btnOpenAsXml.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
             _btnOpenAsXml.TextImageRelation = TextImageRelation.TextBeforeImage;
             _btnOpenAsXml.ToolTipText = Strings.Label_OpenResourceAsXml;
-            _btnOpenAsXml.Click += btnOpenAsXml_Click;
+            _btnOpenAsXml.Click += WeakEventHandler.Wrap(btnOpenAsXml_Click, (eh) => _btnOpenAsXml.Click -= eh);
 
             UpdateConnectionList();
             UpdateNavigationState();
@@ -113,25 +114,25 @@
             });
         }
 
-        void OnSiteExplorerItemsSelected(object sender, RepositoryItem[] items)
+        void OnSiteExplorerItemsSelected(object sender, RepositoryItemEventArgs e)
         {
-            if (items == null)
+            if (e.Items == null)
                 return;
 
-            if (items.Length != 1)
+            if (e.Items.Length != 1)
                 return;
 
-            var idx = _cmbActiveConnections.Items.IndexOf(items[0].ConnectionName);
+            var idx = _cmbActiveConnections.Items.IndexOf(e.Items[0].ConnectionName);
             if (idx >= 0)
             {
-                _cmbResourceId.Text = items[0].ResourceId;
+                _cmbResourceId.Text = e.Items[0].ResourceId;
                 _cmbActiveConnections.SelectedIndex = idx;
             }
         }
 
-        void OnViewActivated(object sender, Shared.UI.IViewContent content)
+        void OnViewActivated(object sender, ViewEventArgs e)
         {
-            var ed = content as IEditorViewContent;
+            var ed = e.View as IEditorViewContent;
             if (ed != null && !ed.IsNew)
             {
                 var conn = ed.Resource.CurrentConnection;
@@ -181,12 +182,12 @@
             _btnGo.Enabled = _btnOpenAsXml.Enabled = ResourceIdentifier.Validate(_cmbResourceId.Text) && !ResourceIdentifier.IsFolderResource(_cmbResourceId.Text);
         }
 
-        void OnConnectionRemoved(object sender, string name)
+        void OnConnectionRemoved(object sender, ServerConnectionEventArgs e)
         {
             UpdateConnectionList();
         }
 
-        void OnConnectionAdded(object sender, string name)
+        void OnConnectionAdded(object sender, ServerConnectionEventArgs e)
         {
             UpdateConnectionList();
         }

Modified: trunk/Tools/Maestro/Maestro.Base/UI/ResourcePropertiesDialog.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/ResourcePropertiesDialog.Designer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/ResourcePropertiesDialog.Designer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -128,7 +128,6 @@
             this.CustomTab.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
             this.ReferenceTab.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.Panel2.SuspendLayout();
             this.splitContainer1.SuspendLayout();
@@ -793,7 +792,6 @@
             this.ReferenceTab.ResumeLayout(false);
             this.splitContainer1.Panel1.ResumeLayout(false);
             this.splitContainer1.Panel2.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
             this.splitContainer1.ResumeLayout(false);
             this.OutReferences.ResumeLayout(false);
             this.OutReferences.PerformLayout();

Modified: trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Base/UI/SiteExplorer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -53,7 +53,7 @@
             InitializeComponent();
             Application.Idle += new EventHandler(OnIdle);
             ndResource.ToolTipProvider = new RepositoryItemToolTipProvider();
-            ndResource.DrawText += new EventHandler<Aga.Controls.Tree.NodeControls.DrawEventArgs>(OnNodeDrawText);
+            ndResource.DrawText += WeakEventHandler.Wrap<EventHandler<Aga.Controls.Tree.NodeControls.DrawEventArgs>>(OnNodeDrawText, (eh) => ndResource.DrawText -= eh);
 
             var ts = ToolbarService.CreateToolStripItems("/Maestro/Shell/SiteExplorer/Toolbar", this, true); //NOXLATE
             tsSiteExplorer.Items.AddRange(ts);
@@ -66,7 +66,7 @@
             trvResources.Model = _model;
 
             Workbench wb = Workbench.Instance;
-            wb.ActiveDocumentChanged += OnActiveDocumentChanged;
+            wb.ActiveDocumentChanged += WeakEventHandler.Wrap(OnActiveDocumentChanged, (eh) => wb.ActiveDocumentChanged -= eh);
         }
 
         void OnActiveDocumentChanged(object sender, EventArgs e)
@@ -118,7 +118,7 @@
 
             var h = this.ItemsSelected;
             if (h != null)
-                h(this, this.SelectedItems);
+                h(this, new RepositoryItemEventArgs(this.SelectedItems));
         }
 
         public event RepositoryItemEventHandler ItemsSelected;

Modified: trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -49,7 +49,7 @@
             _ext = ext;
             var names = new List<string>(qualifiedClassNames);
             cmbBaseClass.DataSource = names;
-            ext.PropertyChanged += (sender, e) => { OnResourceChanged(); };
+            ext.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnExtensionPropertyChanged, (eh) => ext.PropertyChanged -= eh);
 
             //HACK
             if (string.IsNullOrEmpty(_ext.FeatureClass))
@@ -58,6 +58,11 @@
             ComboBoxBinder.BindSelectedIndexChanged(cmbBaseClass, "SelectedItem", ext, "FeatureClass"); //NOXLATE
         }
 
+        void OnExtensionPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            OnResourceChanged();
+        }
+
         public void Bind(IEditorService service)
         {
             service.RegisterCustomNotifier(this);

Modified: trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -171,7 +171,7 @@
                     break;
             }
 
-            _rel.PropertyChanged += (sender, e) => { OnResourceChanged(); };
+            _rel.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnRelationPropertyChanged, (eh) => _rel.PropertyChanged -= eh);
 
             foreach (var join in _rel.RelateProperty)
             {
@@ -180,6 +180,11 @@
             _propertyJoins.ListChanged += new ListChangedEventHandler(OnPropertyJoinListChanged);
         }
 
+        void OnRelationPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            OnResourceChanged();
+        }
+
         private void OnResourceChanged()
         {
             var handler = this.ResourceChanged;

Modified: trunk/Tools/Maestro/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -69,7 +69,7 @@
                     node.Text = ext.Name;
                     node.ToolTipText = string.Format(Strings.ExtendedClassTooltip, ext.FeatureClass);
 
-                    ext.PropertyChanged += (s, evt) =>
+                    PropertyChangedEventHandler extPropChange = (s, evt) =>
                     {
                         if (evt.PropertyName == "Name") //NOXLATE
                         {
@@ -80,6 +80,7 @@
                             node.ToolTipText = string.Format(Strings.ExtendedClassTooltip, ext.FeatureClass);
                         }
                     };
+                    ext.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(extPropChange, (eh) => ext.PropertyChanged -= eh);
 
                     trvExtensions.Nodes.Add(node);
 
@@ -94,7 +95,7 @@
                             cNode.Text = calc.Name;
                             cNode.ToolTipText = calc.Expression;
 
-                            calc.PropertyChanged += (s, evt) =>
+                            PropertyChangedEventHandler calcChange = (s, evt) =>
                             {
                                 if (evt.PropertyName == "Name") //NOXLATE
                                 {
@@ -105,6 +106,7 @@
                                     cNode.ToolTipText = calc.Expression;
                                 }
                             };
+                            calc.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(calcChange, (eh) => calc.PropertyChanged -= eh);
 
                             node.Nodes.Add(cNode);
                         }
@@ -119,13 +121,14 @@
 
                             jNode.Text = join.Name;
 
-                            join.PropertyChanged += (s, evt) =>
+                            PropertyChangedEventHandler joinChange = (s, evt) =>
                             {
                                 if (evt.PropertyName == "Name") //NOXLATE
                                 {
                                     jNode.Text = join.Name;
                                 }
                             };
+                            join.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(joinChange, (eh) => join.PropertyChanged -= eh);
 
                             node.Nodes.Add(jNode);
                         }
@@ -158,7 +161,7 @@
             TreeNode node = new TreeNode();
             node.Tag = ext;
             node.ImageIndex = node.SelectedImageIndex = IDX_EXTENSION;
-            ext.PropertyChanged += (s, evt) =>
+            PropertyChangedEventHandler extChange = (s, evt) =>
             {
                 if (evt.PropertyName == "Name") //NOXLATE
                 {
@@ -169,6 +172,7 @@
                     node.ToolTipText = string.Format(Strings.ExtendedClassTooltip, ext.FeatureClass);
                 }
             };
+            ext.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(extChange, (eh) => ext.PropertyChanged -= eh);
 
             _fs.AddExtension(ext);
             OnResourceChanged();
@@ -195,7 +199,7 @@
                     var cNode = new TreeNode();
                     cNode.ImageIndex = cNode.SelectedImageIndex = IDX_CALC;
                     cNode.Tag = calc;
-                    calc.PropertyChanged += (s, evt) =>
+                    PropertyChangedEventHandler calcChange = (s, evt) =>
                     {
                         if (evt.PropertyName == "Name") //NOXLATE
                         {
@@ -206,6 +210,7 @@
                             cNode.ToolTipText = calc.Expression;
                         }
                     };
+                    calc.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(calcChange, (eh) => calc.PropertyChanged -= eh);
 
                     node.Nodes.Add(cNode);
                     node.Expand();
@@ -236,13 +241,14 @@
                     var jNode = new TreeNode();
                     jNode.Tag = join;
                     jNode.ImageIndex = jNode.SelectedImageIndex = IDX_JOIN;
-                    join.PropertyChanged += (s, evt) =>
+                    PropertyChangedEventHandler joinChange = (s, evt) =>
                     {
                         if (evt.PropertyName == "Name") //NOXLATE
                         {
                             jNode.Text = join.Name;
                         }
                     };
+                    join.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(joinChange, (eh) => join.PropertyChanged -= eh);
 
                     node.Nodes.Add(jNode);
                     node.Expand();

Modified: trunk/Tools/Maestro/Maestro.Editors/Fusion/MapSettingsCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/Fusion/MapSettingsCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/Fusion/MapSettingsCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -78,11 +78,12 @@
             item.ImageIndex = 0;
             item.Text = item.Name = group.id;
             item.Tag = group;
-            group.PropertyChanged += (s, e) =>
+            PropertyChangedEventHandler groupChange = (s, e) =>
             {
                 if (e.PropertyName == "id") //NOXLATE
                     item.Text = group.id;
             };
+            group.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(groupChange, (eh) => group.PropertyChanged -= eh);
             lstMaps.Items.Add(item);
         }
 

Modified: trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetManagementDialog.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetManagementDialog.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetManagementDialog.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -26,6 +26,7 @@
 using System.Windows.Forms;
 using OSGeo.MapGuide.ObjectModels.ApplicationDefinition;
 using System.Xml;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.Fusion
 {
@@ -106,11 +107,12 @@
 
             item.IsDockable = _context.IsWidgetDockable(widget.Type);
 
-            widget.PropertyChanged += (s, e) =>
+            PropertyChangedEventHandler widgetChange = (s, e) =>
             {
                 if (e.PropertyName == "Name") //NOXLATE
                     item.Name = widget.Name;
             };
+            widget.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(widgetChange, (eh) => widget.PropertyChanged -= eh);
 
             _items.Add(item);
         }

Modified: trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetSettingsCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetSettingsCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/Fusion/WidgetSettingsCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -220,7 +220,7 @@
                         node.Text = ((IFlyoutItem)item).Label;
                         node.Tag = item;
 
-                        item.PropertyChanged += (s, evt) =>
+                        PropertyChangedEventHandler itemChange = (s, evt) =>
                         {
                             if (evt.PropertyName == "Label") //NOXLATE
                             {
@@ -228,6 +228,7 @@
                                 OnResourceChanged();
                             }
                         };
+                        item.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(itemChange, (eh) => item.PropertyChanged -= eh);
                     }
                     break;
                 case UiItemFunctionType.Separator:
@@ -243,7 +244,7 @@
                         node.Text = ((IWidgetItem)item).Widget;
                         node.Tag = item;
 
-                        item.PropertyChanged += (s, evt) =>
+                        PropertyChangedEventHandler itemChange = (s, evt) =>
                         {
                             if (evt.PropertyName == "Widget") //NOXLATE
                             {
@@ -251,6 +252,7 @@
                                 OnResourceChanged();
                             }
                         };
+                        item.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(itemChange, (eh) => item.PropertyChanged -= eh);
                     }
                     break;
             }

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Drawing/DrawingLayerSettingsCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Drawing/DrawingLayerSettingsCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Drawing/DrawingLayerSettingsCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -28,6 +28,7 @@
 using System.Diagnostics;
 using OSGeo.MapGuide.ObjectModels.LayerDefinition;
 using Maestro.Editors.Generic;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.LayerDefinition.Drawing
 {
@@ -102,9 +103,14 @@
             TextBoxBinder.BindText(txtMaxScale, maxBinding);
 
             //This is not the root object so no change listeners have been subscribed
-            _dlayer.PropertyChanged += (sender, e) => { OnResourceChanged(); };
+            _dlayer.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnDrawingLayerPropertyChanged, (eh) => _dlayer.PropertyChanged -= eh);
         }
 
+        void OnDrawingLayerPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            OnResourceChanged();
+        }
+
         private void PopulateSheets()
         {
             _sheets.Clear();

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/LayerPropertiesSectionCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/LayerPropertiesSectionCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/LayerPropertiesSectionCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -56,10 +56,8 @@
             }
 
             _props = new List<INameStringPair>(_vl.PropertyMapping);
-            //Modifying the visibility constitutes a change in the resource
-            //_props.ListChanged += OnPropertyListChanged;
             PopulatePropertyList();
-            _vl.PropertyChanged += OnVectorLayerPropertyChanged;
+            _vl.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnVectorLayerPropertyChanged, (eh) => _vl.PropertyChanged -= eh);
         }
 
         protected override void UnsubscribeEventHandlers()

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Raster/RasterLayerSettingsSectionCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Raster/RasterLayerSettingsSectionCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Raster/RasterLayerSettingsSectionCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -64,7 +64,7 @@
             TextBoxBinder.BindText(txtFeatureSource, _rl, "ResourceId"); //NOXLATE
             TextBoxBinder.BindText(txtFeatureClass, _rl, "FeatureName"); //NOXLATE
             TextBoxBinder.BindText(txtGeometry, _rl, "Geometry"); //NOXLATE
-            _rl.PropertyChanged += OnRasterLayerPropertyChanged;
+            _rl.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnRasterLayerPropertyChanged, (eh) => _rl.PropertyChanged -= eh);
         }
 
         void OnRasterLayerPropertyChanged(object sender, PropertyChangedEventArgs e)

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/GridEditor/VectorScaleRangeGrid.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/GridEditor/VectorScaleRangeGrid.Designer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/GridEditor/VectorScaleRangeGrid.Designer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -53,7 +53,6 @@
             this.TAB_AREAS.SuspendLayout();
             this.TAB_POINTS.SuspendLayout();
             this.TAB_COMPOSITE.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.SuspendLayout();
             this.toolStrip1.SuspendLayout();
@@ -298,7 +297,6 @@
             this.TAB_COMPOSITE.ResumeLayout(false);
             this.splitContainer1.Panel1.ResumeLayout(false);
             this.splitContainer1.Panel1.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
             this.splitContainer1.ResumeLayout(false);
             this.toolStrip1.ResumeLayout(false);
             this.toolStrip1.PerformLayout();

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/Scales/SymbolInstancesDialog.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/Scales/SymbolInstancesDialog.Designer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/Scales/SymbolInstancesDialog.Designer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -45,13 +45,11 @@
             this.symPreview = new System.Windows.Forms.PictureBox();
             this.btnRefresh = new System.Windows.Forms.Button();
             this.btnEditInstanceProperties = new System.Windows.Forms.Button();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.SuspendLayout();
             this.groupBox1.SuspendLayout();
             this.toolStrip1.SuspendLayout();
             this.groupBox2.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.symPreview)).BeginInit();
             this.SuspendLayout();
             // 
             // btnClose

Modified: trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -85,7 +85,7 @@
                 txtTooltip.Text = _vl.ToolTip;
 
                 //This is not the root object so no change listeners have been subscribed
-                _vl.PropertyChanged += OnVectorLayerPropertyChanged;
+                _vl.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnVectorLayerPropertyChanged, (eh) => _vl.PropertyChanged -= eh);
             }
             finally
             {

Modified: trunk/Tools/Maestro/Maestro.Editors/LoadProcedure/LoadTargetCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/LoadProcedure/LoadTargetCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/LoadProcedure/LoadTargetCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -27,6 +27,7 @@
 using Maestro.Shared.UI;
 using Maestro.Editors.Common;
 using OSGeo.MapGuide.ObjectModels.LoadProcedure;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.LoadProcedure
 {
@@ -58,7 +59,7 @@
             TextBoxBinder.BindText(txtLayerRoot, _fProc, "LayersPath");
             TextBoxBinder.BindText(txtLayerFolderName, _fProc, "LayersFolder");
 
-            _fProc.PropertyChanged += OnLoadProcedurePropertyChanged;
+            _fProc.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnLoadProcedurePropertyChanged, (eh) => _fProc.PropertyChanged -= eh);
         }
 
         protected override void UnsubscribeEventHandlers()

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -26,6 +26,7 @@
 using System.Windows.Forms;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
 using Maestro.Shared.UI;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.MapDefinition
 {
@@ -51,7 +52,7 @@
             {
                 _mdf = map;
                 _el = group;
-                group.PropertyChanged += new PropertyChangedEventHandler(OnGroupChanged);
+                group.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnGroupChanged, (eh) => group.PropertyChanged -= eh);
                 string currentName = group.Name;
                 txtName.Text = currentName;
                 //TextBoxBinder.BindText(txtName, group, "Name");
@@ -84,7 +85,7 @@
             {
                 _mdf = map;
                 _el = group;
-                group.PropertyChanged += new PropertyChangedEventHandler(OnGroupChanged);
+                group.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnGroupChanged, (eh) => group.PropertyChanged -= eh);
 
                 txtName.Text = group.Name;
                 TextBoxBinder.BindText(txtLegendLabel, group, "LegendLabel");

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -48,7 +48,7 @@
         public LayerPropertiesCtrl(IMapLayer layer, IResourceService resSvc, IEditorService edSvc)
             : this()
         {
-            layer.PropertyChanged += new PropertyChangedEventHandler(OnLayerChanged);
+            layer.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnLayerChanged, (eh) => layer.PropertyChanged -= eh);
             _resSvc = resSvc;
             _edSvc = edSvc;
 
@@ -60,7 +60,7 @@
         public LayerPropertiesCtrl(IBaseMapLayer layer, IResourceService resSvc, IEditorService edSvc)
             : this()
         {
-            layer.PropertyChanged += new PropertyChangedEventHandler(OnLayerChanged);
+            layer.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnLayerChanged, (eh) => layer.PropertyChanged -= eh);
             _resSvc = resSvc;
             _edSvc = edSvc;
 

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -52,18 +52,15 @@
             this.lblSelected = new System.Windows.Forms.ToolStripStatusLabel();
             this.lblScale = new System.Windows.Forms.ToolStripStatusLabel();
             this.mapStatusTracker = new Maestro.MapViewer.MapStatusTracker();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.Panel2.SuspendLayout();
             this.splitContainer1.SuspendLayout();
             this.tabLayersAndGroups.SuspendLayout();
             this.TAB_LEGEND.SuspendLayout();
             this.TAB_DRAW_ORDER.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit();
             this.splitContainer3.Panel1.SuspendLayout();
             this.splitContainer3.Panel2.SuspendLayout();
             this.splitContainer3.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
             this.splitContainer2.Panel1.SuspendLayout();
             this.splitContainer2.Panel2.SuspendLayout();
             this.splitContainer2.SuspendLayout();
@@ -276,18 +273,15 @@
             resources.ApplyResources(this, "$this");
             this.splitContainer1.Panel1.ResumeLayout(false);
             this.splitContainer1.Panel2.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
             this.splitContainer1.ResumeLayout(false);
             this.tabLayersAndGroups.ResumeLayout(false);
             this.TAB_LEGEND.ResumeLayout(false);
             this.TAB_DRAW_ORDER.ResumeLayout(false);
             this.splitContainer3.Panel1.ResumeLayout(false);
             this.splitContainer3.Panel2.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit();
             this.splitContainer3.ResumeLayout(false);
             this.splitContainer2.Panel1.ResumeLayout(false);
             this.splitContainer2.Panel2.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
             this.splitContainer2.ResumeLayout(false);
             this.tabRepo.ResumeLayout(false);
             this.TAB_REPO.ResumeLayout(false);

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapLayersSectionCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapLayersSectionCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapLayersSectionCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -47,9 +47,9 @@
         public MapLayersSectionCtrl()
         {
             InitializeComponent();
-            trvBaseLayers.KeyUp += new KeyEventHandler(trvBaseLayers_KeyUp);
-            trvLayerDrawingOrder.KeyUp += new KeyEventHandler(trvLayerDrawingOrder_KeyUp);
-            trvLayersGroup.KeyUp += new KeyEventHandler(trvLayersGroup_KeyUp);
+            trvBaseLayers.KeyUp += WeakEventHandler.Wrap<KeyEventHandler>(trvBaseLayers_KeyUp, (eh) => trvBaseLayers.KeyUp -= eh);
+            trvLayerDrawingOrder.KeyUp += WeakEventHandler.Wrap<KeyEventHandler>(trvLayerDrawingOrder_KeyUp, (eh) => trvLayerDrawingOrder.KeyUp -= eh);
+            trvLayersGroup.KeyUp += WeakEventHandler.Wrap<KeyEventHandler>(trvLayersGroup_KeyUp, (eh) => trvLayersGroup.KeyUp -= eh);
         }
 
         void trvLayersGroup_KeyUp(object sender, KeyEventArgs e)
@@ -200,9 +200,6 @@
             btnConvertLayerGroupToBaseGroup.Enabled = true;
 
             propertiesPanel.Controls.Clear();
-            //var item = new GroupPropertiesCtrl(_map, group.Tag);
-            //item.GroupChanged += (s, evt) => { OnResourceChanged(); };
-            //item.Dock = DockStyle.Fill;
             var item = CreateGroupControl(group);
             _activeLayer = null;
             propertiesPanel.Controls.Add(item);
@@ -385,7 +382,8 @@
             commCtrl.SelectedObject = new GroupItemDesigner(group);
 
             var item = new GroupPropertiesCtrl(_map, group.Tag);
-            item.GroupChanged += (s, evt) => { OnResourceChanged(); };
+            //item.GroupChanged += (s, evt) => { OnResourceChanged(); };
+            item.GroupChanged += WeakEventHandler.Wrap((s, evt) => OnResourceChanged(), (eh) => item.GroupChanged -= eh);
             item.Dock = DockStyle.Top;
 
             ctrl.Controls.Add(commCtrl);
@@ -442,7 +440,8 @@
             commCtrl.SelectedObject = new BaseGroupItemDesigner(group);
 
             var item = new GroupPropertiesCtrl(_map, group.Tag);
-            item.GroupChanged += (s, evt) => { OnResourceChanged(); };
+            //item.GroupChanged += (s, evt) => { OnResourceChanged(); };
+            item.GroupChanged += WeakEventHandler.Wrap((s, evt) => OnResourceChanged(), (eh) => item.GroupChanged -= eh);
             item.Dock = DockStyle.Top;
 
             ctrl.Controls.Add(commCtrl);
@@ -463,7 +462,8 @@
             commCtrl.SelectedObject = new BaseLayerItemDesigner(layer);
 
             var item = new LayerPropertiesCtrl(layer.Tag, _edSvc.ResourceService, _edSvc);
-            item.LayerChanged += (s, evt) => { OnResourceChanged(); };
+            //item.LayerChanged += (s, evt) => { OnResourceChanged(); };
+            item.LayerChanged += WeakEventHandler.Wrap((s, evt) => OnResourceChanged(), (eh) => item.LayerChanged -= eh);
             item.Dock = DockStyle.Top;
 
             ctrl.Controls.Add(commCtrl);
@@ -484,7 +484,8 @@
             commCtrl.SelectedObject = new LayerItemDesigner(layer);
 
             var item = new LayerPropertiesCtrl(layer.Tag, _edSvc.ResourceService, _edSvc);
-            item.LayerChanged += (s, evt) => { OnResourceChanged(); };
+            //item.LayerChanged += (s, evt) => { OnResourceChanged(); };
+            item.LayerChanged += WeakEventHandler.Wrap((s, evt) => OnResourceChanged(), (eh) => item.LayerChanged -= eh);
             item.Dock = DockStyle.Top;
 
             ctrl.Controls.Add(commCtrl);

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -86,7 +86,7 @@
             {
                 _map.BackgroundColor = cmbBackgroundColor.CurrentColor;
             };
-            _map.PropertyChanged += (sender, e) =>
+            PropertyChangedEventHandler mapChanged = (sender, e) =>
             {
                 if (e.PropertyName == "BackgroundColor")
                 {
@@ -97,6 +97,7 @@
                     UpdateExtentsFromMap();
                 }
             };
+            _map.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(mapChanged, (eh) => _map.PropertyChanged -= eh);
 
             txtLowerX.Text = _map.Extents.MinX.ToString(CultureInfo.InvariantCulture);
             txtLowerY.Text = _map.Extents.MinY.ToString(CultureInfo.InvariantCulture);
@@ -155,11 +156,13 @@
                     _map.Extents.MaxY = d;
             };
 
-            _map.Extents.PropertyChanged += (sender, e) => 
+            PropertyChangedEventHandler extChange = (sender, e) => 
             {
                 UpdateExtentsFromMap();
                 OnResourceChanged(); 
             };
+            var ext = _map.Extents;
+            ext.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(extChange, (eh) => ext.PropertyChanged -= eh);
         }
 
         private void UpdateExtentsFromMap()

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapTreeModels.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapTreeModels.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/MapTreeModels.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -24,6 +24,7 @@
 using System.Drawing;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
 using System.ComponentModel;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.MapDefinition
 {
@@ -56,7 +57,7 @@
         public LayerItem(IMapLayer layer)
             : base(layer.Name, Properties.Resources.layer, layer)
         {
-            layer.PropertyChanged += OnPropertyChanged;
+            layer.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnPropertyChanged, (eh) => layer.PropertyChanged -= eh);
         }
 
         void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -73,7 +74,7 @@
         public GroupItem(IMapLayerGroup grp)
             : base(grp.Name, Properties.Resources.folder_horizontal, grp)
         {
-            grp.PropertyChanged += OnPropertyChanged;
+            grp.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnPropertyChanged, (eh) => grp.PropertyChanged -= eh);
         }
 
         void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -90,7 +91,7 @@
         public BaseLayerItem(IBaseMapLayer layer, IBaseMapGroup parent)
             : base(layer.Name, Properties.Resources.layer, layer)
         {
-            layer.PropertyChanged += OnPropertyChanged;
+            layer.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnPropertyChanged, (eh) => layer.PropertyChanged -= eh);
             this.Parent = parent;
         }
 
@@ -114,7 +115,7 @@
         public BaseLayerGroupItem(IBaseMapGroup group)
             : base(group.Name, Properties.Resources.folder_horizontal, group)
         {
-            group.PropertyChanged += OnPropertyChanged;
+            group.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnPropertyChanged, (eh) => group.PropertyChanged -= eh); ;
         }
 
         void OnPropertyChanged(object sender, PropertyChangedEventArgs e)

Modified: trunk/Tools/Maestro/Maestro.Editors/ResourceEditorServiceBase.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/ResourceEditorServiceBase.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/ResourceEditorServiceBase.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -122,7 +122,7 @@
                 _conn.ResourceService.CopyResource(this.ResourceID, copy, true);
 
                 _editCopy = _conn.ResourceService.GetResource(copy);
-                _editCopy.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(OnResourcePropertyChanged);
+                _editCopy.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnResourcePropertyChanged, (eh) => _editCopy.PropertyChanged -= eh);
             }
             return _editCopy;
         }

Modified: trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/CompoundSymbolDefinitionEditorCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/CompoundSymbolDefinitionEditorCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/CompoundSymbolDefinitionEditorCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -108,11 +108,13 @@
             {
                 var inline = (ISimpleSymbolInlineReference)symRef;
                 li.Text = inline.SimpleSymbolDefinition.Name;
-                inline.SimpleSymbolDefinition.PropertyChanged += (s, e) =>
+                PropertyChangedEventHandler symChange = (s, e) =>
                 {
                     if (e.PropertyName == "Name" && li != null)
                         li.Text = inline.SimpleSymbolDefinition.Name;
                 };
+                var simpleSym = inline.SimpleSymbolDefinition;
+                simpleSym.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(symChange, (eh) => simpleSym.PropertyChanged -= eh);
                 li.ImageIndex = 0;
                 li.Tag = symRef;
                 lstSymbols.Items.Add(li);

Modified: trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/SymbolField.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/SymbolField.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/SymbolDefinition/SymbolField.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -348,7 +348,7 @@
                 var inp = _boundObject as INotifyPropertyChanged;
                 if (inp != null)
                 {
-                    inp.PropertyChanged += OnBoundObjectPropertyChanged;
+                    inp.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnBoundObjectPropertyChanged, (eh) => inp.PropertyChanged -= eh);
                 }
             }
             finally

Modified: trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/InvokeURLCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/InvokeURLCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/InvokeURLCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -28,6 +28,7 @@
 using Maestro.Shared.UI;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
 using Maestro.Editors.Common;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.WebLayout.Commands
 {
@@ -69,7 +70,7 @@
             _params.AddingNew += OnAddingNew;
             lstLayers.DataSource = invokeUrlCommandType.LayerSet.Layer;
 
-            invokeUrlCommandType.PropertyChanged += OnCommandPropertyChanged;
+            invokeUrlCommandType.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnCommandPropertyChanged, (eh) => invokeUrlCommandType.PropertyChanged -= eh);
             _cmd = invokeUrlCommandType;
         }
 

Modified: trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/SearchCmdCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/SearchCmdCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/WebLayout/Commands/SearchCmdCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -66,7 +66,8 @@
             _cmd = searchCommandType;
 
             _wl = (IWebLayout)_edsvc.GetEditedResource();
-            _wl.Map.PropertyChanged += OnWebLayoutPropertyChanged;
+            var wlMap = _wl.Map;
+            wlMap.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => wlMap.PropertyChanged -= eh);
 
             LoadLayers();
 

Modified: trunk/Tools/Maestro/Maestro.Editors/WebLayout/MenuEditorCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/WebLayout/MenuEditorCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/WebLayout/MenuEditorCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -27,6 +27,7 @@
 using Aga.Controls.Tree;
 using OSGeo.MapGuide.ObjectModels.WebLayout;
 using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.WebLayout
 {
@@ -155,7 +156,7 @@
                     mi.Text = cmd.Name;
             };
             _customCommandListeners[mi] = handler;
-            cmd.PropertyChanged += handler;
+            cmd.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(handler, (eh) => cmd.PropertyChanged -= eh);
             mi.Tag = cmd;
             tsi.DropDown.Items.Add(mi);
         }
@@ -210,7 +211,7 @@
                         trvMenuItems.Refresh();
                     }
                 };
-                cmd.PropertyChanged += handler;
+                cmd.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(handler, (eh) => cmd.PropertyChanged -= eh);
 
                 if (trvMenuItems.SelectedNode != null)
                 {

Modified: trunk/Tools/Maestro/Maestro.Editors/WebLayout/WebLayoutSettingsCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/WebLayout/WebLayoutSettingsCtrl.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Editors/WebLayout/WebLayoutSettingsCtrl.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -103,16 +103,24 @@
             TextBoxBinder.BindText(numInfoPaneWidth, _wl.InformationPane, "Width");
             TextBoxBinder.BindText(numTaskPaneWidth, _wl.TaskPane, "Width");
 
-            _wl.PropertyChanged += OnWebLayoutPropertyChanged;
-            _view.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.Map.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.ContextMenu.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.InformationPane.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.StatusBar.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.TaskPane.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.TaskPane.TaskBar.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.ToolBar.PropertyChanged += OnWebLayoutPropertyChanged;
-            _wl.ZoomControl.PropertyChanged += OnWebLayoutPropertyChanged;
+            _wl.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => _wl.PropertyChanged -= eh);
+            _view.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => _view.PropertyChanged -= eh);
+            var wlMap = _wl.Map;
+            wlMap.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => wlMap.PropertyChanged -= eh);
+            var ctx = _wl.ContextMenu;
+            ctx.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => ctx.PropertyChanged -= eh);
+            var info = _wl.InformationPane;
+            info.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => info.PropertyChanged -= eh);
+            var stat = _wl.StatusBar;
+            stat.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => stat.PropertyChanged -= eh);
+            var tpane = _wl.TaskPane;
+            tpane.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => tpane.PropertyChanged -= eh);
+            var tbar = tpane.TaskBar;
+            tbar.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => tbar.PropertyChanged -= eh);
+            var toolbar = _wl.ToolBar;
+            toolbar.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => toolbar.PropertyChanged -= eh);
+            var zoom = _wl.ZoomControl;
+            zoom.PropertyChanged += WeakEventHandler.Wrap<PropertyChangedEventHandler>(OnWebLayoutPropertyChanged, (eh) => zoom.PropertyChanged -= eh);
         }
 
         private void GeneratePreviewUrl()

Modified: trunk/Tools/Maestro/Maestro.Shared.UI/ViewContentManagerBase.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Shared.UI/ViewContentManagerBase.cs	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/Maestro.Shared.UI/ViewContentManagerBase.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -139,7 +139,7 @@
                         cnt.Activate();
                         var h = this.ViewActivated;
                         if (h != null)
-                            h(this, cnt);
+                            h(this, new ViewEventArgs(cnt));
                         //wb.CheckContainerStatus();
                         return;
                     }
@@ -211,7 +211,7 @@
                         cnt.Activate();
                         var h = this.ViewActivated;
                         if (h != null)
-                            h(this, cnt);
+                            h(this, new ViewEventArgs(cnt));
                         //wb.CheckContainerStatus();
                         return (T)cnt;
                     }
@@ -230,10 +230,20 @@
         }
     }
 
+    public class ViewEventArgs : EventArgs 
+    {
+        public ViewEventArgs(IViewContent content)
+        {
+            this.View = content;
+        }
+
+        public IViewContent View { get; private set; }
+    }
+
     /// <summary>
     /// 
     /// </summary>
     /// <param name="sender"></param>
-    /// <param name="content"></param>
-    public delegate void ViewEventHandler(object sender, IViewContent content);
+    /// <param name="e"></param>
+    public delegate void ViewEventHandler(object sender, ViewEventArgs e);
 }

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2014-04-08 09:49:37 UTC (rev 8016)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2014-04-09 11:16:33 UTC (rev 8017)
@@ -407,6 +407,7 @@
     <Compile Include="Tile\RenderThread.cs" />
     <Compile Include="Utf8XmlWriter.cs" />
     <Compile Include="Utility.cs" />
+    <Compile Include="WeakEventHandler.cs" />
     <Compile Include="XmlValidator.cs" />
   </ItemGroup>
   <ItemGroup>

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/WeakEventHandler.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/WeakEventHandler.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/WeakEventHandler.cs	2014-04-09 11:16:33 UTC (rev 8017)
@@ -0,0 +1,128 @@
+#region Disclaimer / License
+// Copyright (C) 2014, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Reflection;
+
+namespace OSGeo.MapGuide.MaestroAPI
+{
+    // Original Source: http://www.wintellect.com/blogs/jeffreyr/weak-event-handlers
+
+    public static class WeakEventHandler
+    {
+        private class WeakEventHandlerImpl
+        {
+            protected readonly WeakReference m_wrTarget; // WeakReference to original delegate's target object 
+            protected Delegate m_openEventHandler;       // "Open" delegate to invoke original target's delegate method 
+
+            public WeakEventHandlerImpl(Delegate d) { m_wrTarget = new WeakReference(d.Target); }
+
+            // Match is used to compare a WeakEventHandlerImpl object with an actual delegate. 
+            // Typically used to remove a WeakEventHandlerImpl from an event collection. 
+            public Boolean Match(Delegate strongEventHandler)
+            {
+                // Returns true if original target & method match the WeakEventHandlerImpl's Target & method 
+                return (m_wrTarget.Target == strongEventHandler.Target) && (m_openEventHandler.Method == strongEventHandler.Method);
+            }
+        }
+
+        // "Open" delegate definition to quickly invoke original delegate's callback 
+        private delegate void OpenEventHandler<TTarget, TEventArgs>(TTarget target, Object sender, TEventArgs eventArgs)
+            where TTarget : class
+            where TEventArgs : EventArgs;
+
+        // A proxy object that knows how to invoke a callback on an object if it hasn't been GC'd 
+        private sealed class WeakEventHandlerImpl<TEventHandler> : WeakEventHandlerImpl where TEventHandler : class
+        {
+            // Refers to a method that removes a delegate to this proxy object once we know the original target has been GC'd 
+            private readonly Action<TEventHandler> m_cleanup;
+
+            // This is the delegate passed to m_cleanup that needs to be removed from an event 
+            private readonly TEventHandler m_proxyHandler;
+
+            public static TEventHandler Create(TEventHandler eh, Action<TEventHandler> cleanup)
+            {
+                Check.That(eh != null && cleanup != null, "eh != null && cleanup != null");
+                // We don't create weak events for static methods since types don't get GC'd 
+                Delegate d = (Delegate)(Object)eh;  // We know that all event handlers are derived from Delegate 
+                if (d.Target == null) return eh;
+
+                var weh = new WeakEventHandlerImpl<TEventHandler>(d, cleanup);
+                return weh.m_proxyHandler; // Return the delegate to add to the event 
+            }
+
+            private WeakEventHandlerImpl(Delegate d, Action<TEventHandler> cleanup)
+                : base(d)
+            {
+                m_cleanup = cleanup;
+
+                Type targetType = d.Target.GetType();
+                Type eventHandlerType = typeof(TEventHandler);
+                Type eventArgsType = eventHandlerType.IsGenericType
+                   ? eventHandlerType.GetGenericArguments()[0]
+                   : eventHandlerType.GetMethod("Invoke").GetParameters()[1].ParameterType;
+
+                // Create a delegate to the ProxyInvoke method; this delegate is registered with the event 
+                var miProxy = typeof(WeakEventHandlerImpl<TEventHandler>)
+                   .GetMethod("ProxyInvoke", BindingFlags.Instance | BindingFlags.NonPublic)
+                   .MakeGenericMethod(targetType, eventArgsType);
+                m_proxyHandler = (TEventHandler)(Object)Delegate.CreateDelegate(eventHandlerType, this, miProxy);
+
+                // Create an "open" delegate to the original delegate's method; ProxyInvoke calls this 
+                Type openEventHandlerType = typeof(OpenEventHandler<,>).MakeGenericType(d.Target.GetType(), eventArgsType);
+                m_openEventHandler = Delegate.CreateDelegate(openEventHandlerType, null, d.Method);
+            }
+
+            private void ProxyInvoke<TTarget, TEventArgs>(Object sender, TEventArgs e)
+                where TTarget : class
+                where TEventArgs : EventArgs
+            {
+                // If the original target object still exists, call it; else call m_cleanup to unregister our delegate with the event 
+                TTarget target = (TTarget)m_wrTarget.Target;
+                if (target != null)
+                {
+                    ((OpenEventHandler<TTarget, TEventArgs>)m_openEventHandler)(target, sender, e);
+                }
+                else
+                {
+                    m_cleanup(m_proxyHandler);
+                    System.Diagnostics.Debug.WriteLine("Cleanup event handler");
+                }
+            }
+        }
+
+        // We offer this overload because it is so common 
+        public static EventHandler Wrap(EventHandler eh, Action<EventHandler> cleanup)
+        {
+            return WeakEventHandlerImpl<EventHandler>.Create(eh, cleanup);
+        }
+        public static TEventHandler Wrap<TEventHandler>(TEventHandler eh, Action<TEventHandler> cleanup) where TEventHandler : class
+        {
+            return WeakEventHandlerImpl<TEventHandler>.Create(eh, cleanup);
+        }
+        public static EventHandler<TEventArgs> Wrap<TEventArgs>(EventHandler<TEventArgs> eh, Action<EventHandler<TEventArgs>> cleanup) where TEventArgs : EventArgs
+        {
+            return WeakEventHandlerImpl<EventHandler<TEventArgs>>.Create(eh, cleanup);
+        }
+        public static Boolean Match(Delegate weakEventHandler, Delegate strongEventHandler)
+        {
+            return ((WeakEventHandlerImpl)weakEventHandler.Target).Match(strongEventHandler);
+        }
+    }
+}
\ No newline at end of file



More information about the mapguide-commits mailing list