diff --git a/src/DocumentationBrowserViewExtension/DocumentationBrowserView.xaml.cs b/src/DocumentationBrowserViewExtension/DocumentationBrowserView.xaml.cs
index 5303c40e909..ca451bc2aae 100644
--- a/src/DocumentationBrowserViewExtension/DocumentationBrowserView.xaml.cs
+++ b/src/DocumentationBrowserViewExtension/DocumentationBrowserView.xaml.cs
@@ -109,6 +109,13 @@ protected virtual void Dispose(bool disposing)
// Cleanup
this.viewModel.LinkChanged -= NavigateToPage;
this.documentationBrowser.NavigationStarting -= ShouldAllowNavigation;
+ this.documentationBrowser.DpiChanged -= DocumentationBrowser_DpiChanged;
+
+ if (this.documentationBrowser.CoreWebView2 != null)
+ {
+ this.documentationBrowser.CoreWebView2.WebMessageReceived -= CoreWebView2OnWebMessageReceived;
+ }
+
// Note to test writers
// Disposing the document browser will cause future tests
// that uses the Browser component to crash
@@ -116,17 +123,6 @@ protected virtual void Dispose(bool disposing)
{
this.documentationBrowser.Dispose();
}
- this.documentationBrowser.DpiChanged -= DocumentationBrowser_DpiChanged;
- try
- {
- if (this.documentationBrowser.CoreWebView2 != null)
- this.documentationBrowser.CoreWebView2.WebMessageReceived -= CoreWebView2OnWebMessageReceived;
-
- }
- catch (Exception)
- {
- return;
- }
}
async void InitializeAsync()
diff --git a/src/DocumentationBrowserViewExtension/DocumentationBrowserViewExtension.cs b/src/DocumentationBrowserViewExtension/DocumentationBrowserViewExtension.cs
index 0601cf567e4..7e293c1d00a 100644
--- a/src/DocumentationBrowserViewExtension/DocumentationBrowserViewExtension.cs
+++ b/src/DocumentationBrowserViewExtension/DocumentationBrowserViewExtension.cs
@@ -436,6 +436,8 @@ protected virtual void Dispose(bool disposing)
{
this.pmExtension.PackageLoader.PackgeLoaded -= OnPackageLoaded;
}
+
+ PackageDocumentationManager.Instance.MessageLogged -= OnMessageLogged;
PackageDocumentationManager.Instance.Dispose();
}
diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs
index 5253492237b..a46e0216ba2 100644
--- a/src/DynamoCore/Models/DynamoModel.cs
+++ b/src/DynamoCore/Models/DynamoModel.cs
@@ -873,8 +873,8 @@ protected DynamoModel(IStartConfiguration config)
if (!IsServiceMode)
{
SearchModel = new NodeSearchModel(Logger);
- SearchModel.ItemProduced +=
- node => ExecuteCommand(new CreateNodeCommand(node, 0, 0, true, true));
+ SearchModel.ItemProduced += SearchModel_ItemProduced;
+
}
NodeFactory = new NodeFactory();
@@ -1021,6 +1021,11 @@ protected DynamoModel(IStartConfiguration config)
DynamoReady(new ReadyParams(this));
}
+ private void SearchModel_ItemProduced(NodeModel node)
+ {
+ ExecuteCommand(new CreateNodeCommand(node, 0, 0, true, true));
+ }
+
///
/// It returns a PathManager instance based on the mode in order to reuse it's Singleton instance or create a new one
///
@@ -1476,6 +1481,10 @@ public void Dispose()
FeatureFlags.MessageLogged -= LogMessageWrapper;
}
DynamoUtilities.DynamoFeatureFlagsManager.FlagsRetrieved -= CheckFeatureFlagTest;
+ if (!IsServiceMode)
+ {
+ SearchModel.ItemProduced -= SearchModel_ItemProduced;
+ }
}
private void InitializeCustomNodeManager()
@@ -2886,7 +2895,7 @@ public void RemoveWorkspace(WorkspaceModel workspace)
{
OnWorkspaceRemoveStarted(workspace);
if (_workspaces.Remove(workspace))
- {
+ {
if (workspace is HomeWorkspaceModel)
{
workspace.Dispose();
diff --git a/src/DynamoCoreWpf/Controls/NodeAutoCompleteSearchControl.xaml.cs b/src/DynamoCoreWpf/Controls/NodeAutoCompleteSearchControl.xaml.cs
index 4168958d142..d7ddfd9c860 100644
--- a/src/DynamoCoreWpf/Controls/NodeAutoCompleteSearchControl.xaml.cs
+++ b/src/DynamoCoreWpf/Controls/NodeAutoCompleteSearchControl.xaml.cs
@@ -24,7 +24,7 @@ namespace Dynamo.UI.Controls
/// Notice this control shares a lot of logic with InCanvasSearchControl for now
/// But they will diverge eventually because of UI improvements to auto complete.
///
- public partial class NodeAutoCompleteSearchControl
+ public partial class NodeAutoCompleteSearchControl : IDisposable
{
ListBoxItem HighlightedItem;
@@ -45,7 +45,10 @@ public NodeAutoCompleteSearchControl()
if (Application.Current != null)
{
Application.Current.Deactivated += CurrentApplicationDeactivated;
- Application.Current.MainWindow.Closing += NodeAutoCompleteSearchControl_Unloaded;
+ if (Application.Current.MainWindow != null)
+ {
+ Application.Current.MainWindow.Closing += NodeAutoCompleteSearchControl_Unloaded;
+ }
}
HomeWorkspaceModel.WorkspaceClosed += this.CloseAutoCompletion;
}
@@ -55,8 +58,12 @@ private void NodeAutoCompleteSearchControl_Unloaded(object sender, System.Compon
if (Application.Current != null)
{
Application.Current.Deactivated -= CurrentApplicationDeactivated;
- Application.Current.MainWindow.Closing -= NodeAutoCompleteSearchControl_Unloaded;
+ if (Application.Current.MainWindow != null)
+ {
+ Application.Current.MainWindow.Closing -= NodeAutoCompleteSearchControl_Unloaded;
+ }
}
+ HomeWorkspaceModel.WorkspaceClosed -= this.CloseAutoCompletion;
}
private void CurrentApplicationDeactivated(object sender, EventArgs e)
@@ -388,5 +395,10 @@ private void OnSuggestion_Click(object sender, RoutedEventArgs e)
}
ViewModel.PopulateAutoCompleteCandidates();
}
+
+ public void Dispose()
+ {
+ NodeAutoCompleteSearchControl_Unloaded(this,null);
+ }
}
}
diff --git a/src/DynamoCoreWpf/Extensions/ViewExtensionCommandExecutive.cs b/src/DynamoCoreWpf/Extensions/ViewExtensionCommandExecutive.cs
index 20204d670dc..a9cc8910ace 100644
--- a/src/DynamoCoreWpf/Extensions/ViewExtensionCommandExecutive.cs
+++ b/src/DynamoCoreWpf/Extensions/ViewExtensionCommandExecutive.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using Dynamo.Extensions;
using Dynamo.Logging;
using Dynamo.Models;
@@ -7,14 +7,19 @@
namespace Dynamo.Wpf.Extensions
{
- internal class ViewExtensionCommandExecutive : ICommandExecutive
+ internal class ViewExtensionCommandExecutive : ICommandExecutive,IDisposable
{
private readonly DynamoViewModel dynamoViewModel;
public ViewExtensionCommandExecutive(DynamoViewModel model)
{
dynamoViewModel = model;
- MessageLogged += (message) => { dynamoViewModel.Model.Logger.Log(message); };
+ MessageLogged += ViewExtensionCommandExecutive_MessageLogged;
+ }
+
+ private void ViewExtensionCommandExecutive_MessageLogged(ILogMessage message)
+ {
+ dynamoViewModel.Model.Logger.Log(message);
}
public void ExecuteCommand(DynamoModel.RecordableCommand command, string uniqueId, string extensionName)
@@ -42,5 +47,10 @@ private void Log(ILogMessage obj)
var handler = MessageLogged;
if (handler != null) handler(obj);
}
+
+ public void Dispose()
+ {
+ MessageLogged -= ViewExtensionCommandExecutive_MessageLogged;
+ }
}
}
diff --git a/src/DynamoCoreWpf/Extensions/ViewLoadedParams.cs b/src/DynamoCoreWpf/Extensions/ViewLoadedParams.cs
index 387be24c45c..09d11ca2a65 100644
--- a/src/DynamoCoreWpf/Extensions/ViewLoadedParams.cs
+++ b/src/DynamoCoreWpf/Extensions/ViewLoadedParams.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
@@ -120,7 +120,7 @@ public void AddExtensionMenuItem(MenuItem menuItem)
///
public void AddToExtensionsSideBar(IViewExtension viewExtension, ContentControl contentControl)
{
- bool added = dynamoView.AddOrFocusExtensionControl(viewExtension, contentControl);
+ bool added = dynamoView.AddOrFocusExtensionControl(viewExtension, contentControl);
if (added)
{
@@ -223,7 +223,7 @@ public void OpenViewExtension(string extensionName)
{
dynamoViewModel.OnViewExtensionOpenRequest(extensionName);
}
-
+
///
/// Event raised when a component inside Dynamo raises a request to open a view extension.
///
@@ -247,6 +247,13 @@ public event Action ViewExtensionOpenRequestWithParameter
remove => dynamoViewModel.ViewExtensionOpenWithParameterRequest -= value;
}
+ public new void Dispose()
+ {
+ if (CommandExecutive is IDisposable disposable)
+ { disposable.Dispose(); }
+ base.Dispose();
+ }
+
}
///
/// An enum that represents the different possible
diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
index 1f13e7a687d..a128f518531 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
@@ -3421,6 +3421,10 @@ public bool PerformShutdownSequence(ShutdownParams shutdownParams)
BackgroundPreviewViewModel.Dispose();
+ foreach (var wsvm in workspaces)
+ {
+ wsvm.Dispose();
+ }
MainGuideManager?.CloseRealTimeInfoWindow();
model.ShutDown(shutdownParams.ShutdownHost);
diff --git a/src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs b/src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs
index dac21d0b0c7..146e5850afd 100644
--- a/src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Search/SearchViewModel.cs
@@ -403,6 +403,7 @@ public override void Dispose()
{
cate.DisposeTree();
}
+ Model.EntryAdded += AddEntry;
Model.EntryUpdated -= UpdateEntry;
Model.EntryRemoved -= RemoveEntry;
@@ -425,12 +426,7 @@ private void InitializeCore()
searchIconAlignment = System.Windows.HorizontalAlignment.Left;
// When Library changes, sync up
- Model.EntryAdded += entry =>
- {
- InsertEntry(MakeNodeSearchElementVM(entry), entry.Categories);
- RaisePropertyChanged("BrowserRootCategories");
- };
-
+ Model.EntryAdded += AddEntry;
Model.EntryUpdated += UpdateEntry;
Model.EntryRemoved += RemoveEntry;
@@ -440,6 +436,12 @@ private void InitializeCore()
InsertClassesIntoTree(LibraryRootCategories);
}
+ private void AddEntry(NodeSearchElement entry)
+ {
+ InsertEntry(MakeNodeSearchElementVM(entry), entry.Categories);
+ RaisePropertyChanged("BrowserRootCategories");
+ }
+
private IEnumerable CategorizeEntries(IEnumerable entries, bool expanded)
{
var tempRoot = entries.GroupByRecursive(
diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
index 86d6e6b481d..ea55d5c62ba 100644
--- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
+++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
@@ -2892,7 +2892,13 @@ public void Dispose()
dynamoViewModel.SideBarTabItems.CollectionChanged -= this.OnCollectionChanged;
if (fileTrustWarningPopup != null)
+ {
fileTrustWarningPopup.CleanPopup();
+ }
+ //TODO code smell.
+ var workspaceView = this.ChildOfType();
+ workspaceView?.Dispose();
+ (workspaceView?.NodeAutoCompleteSearchBar?.Child as IDisposable)?.Dispose();
}
}
}
diff --git a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
index ffe021f61cf..d684a58f7cf 100644
--- a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
+++ b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
@@ -33,7 +33,7 @@ namespace Dynamo.Views
///
/// Interaction logic for WorkspaceView.xaml
///
- public partial class WorkspaceView
+ public partial class WorkspaceView: IDisposable
{
public enum CursorState
{
@@ -1134,5 +1134,10 @@ private void OnGeometryScaling_Click(object sender, RoutedEventArgs e)
}
GeoScalingPopup.IsOpen = true;
}
+
+ public void Dispose()
+ {
+ RemoveViewModelsubscriptions(ViewModel);
+ }
}
}
diff --git a/src/DynamoManipulation/DynamoManipulationExtension.cs b/src/DynamoManipulation/DynamoManipulationExtension.cs
index 89c10ed3fe3..23d138803da 100644
--- a/src/DynamoManipulation/DynamoManipulationExtension.cs
+++ b/src/DynamoManipulation/DynamoManipulationExtension.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
@@ -174,6 +174,13 @@ private void UnregisterEventHandlers()
BackgroundPreviewViewModel.CanNavigateBackgroundPropertyChanged -= Watch3DViewModelNavigateBackgroundPropertyChanged;
BackgroundPreviewViewModel.ViewMouseDown -= Watch3DViewModelOnViewMouseDown;
}
+
+ var settings = GetRunSettings(WorkspaceModel);
+ if (settings != null)
+ {
+ settings.PropertyChanged -= OnRunSettingsPropertyChanged;
+ }
+
}
private void Watch3DViewModelOnViewMouseDown(object o, MouseButtonEventArgs mouseButtonEventArgs)
diff --git a/src/GraphMetadataViewExtension/GraphMetadataViewModel.cs b/src/GraphMetadataViewExtension/GraphMetadataViewModel.cs
index b06466b33df..ee2151b8308 100644
--- a/src/GraphMetadataViewExtension/GraphMetadataViewModel.cs
+++ b/src/GraphMetadataViewExtension/GraphMetadataViewModel.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Media.Imaging;
@@ -266,6 +266,7 @@ private void MarkCurrentWorkspaceModified()
public void Dispose()
{
this.viewLoadedParams.CurrentWorkspaceChanged -= OnCurrentWorkspaceChanged;
+ this.viewLoadedParams.CurrentWorkspaceCleared += OnCurrentWorkspaceChanged;
if (linterManager != null)
{
linterManager.PropertyChanged -= OnLinterManagerPropertyChange;
diff --git a/src/LibraryViewExtensionWebView2/LibraryViewController.cs b/src/LibraryViewExtensionWebView2/LibraryViewController.cs
index 1bfc43befbe..d00bfa47dc0 100644
--- a/src/LibraryViewExtensionWebView2/LibraryViewController.cs
+++ b/src/LibraryViewExtensionWebView2/LibraryViewController.cs
@@ -622,7 +622,6 @@ public void Dispose()
protected void Dispose(bool disposing)
{
if (!disposing) return;
-
if (observer != null) observer.Dispose();
observer = null;
if (this.dynamoWindow != null)
@@ -636,11 +635,15 @@ protected void Dispose(bool disposing)
}
if (this.browser != null)
{
+ browser.CoreWebView2.RemoveHostObjectFromScript("bridgeTwoWay");
browser.SizeChanged -= Browser_SizeChanged;
browser.Loaded -= Browser_Loaded;
browser.Dispose();
browser = null;
}
+ twoWayScriptingObject.Dispose();
+ dynamoViewModel = null;
+ commandExecutive = null;
}
public static async Task ExecuteScriptFunctionAsync(WebView2 webView2, string functionName, params object[] parameters)
diff --git a/src/LibraryViewExtensionWebView2/ScriptingObject.cs b/src/LibraryViewExtensionWebView2/ScriptingObject.cs
index 6642105bace..e143df61cb1 100644
--- a/src/LibraryViewExtensionWebView2/ScriptingObject.cs
+++ b/src/LibraryViewExtensionWebView2/ScriptingObject.cs
@@ -11,7 +11,7 @@ namespace Dynamo.LibraryViewExtensionWebView2
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
- public class ScriptingObject
+ public class ScriptingObject: IDisposable
{
private LibraryViewController controller;
@@ -20,6 +20,11 @@ public ScriptingObject(LibraryViewController controller)
this.controller = controller;
}
+ public void Dispose()
+ {
+ controller = null;
+ }
+
///
/// Used to get access to the iconResourceProvider and return a base64encoded string version of an icon.
///