diff --git a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
index 209a89ea37b..a44d5554975 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
@@ -482,8 +482,8 @@ public double Zoom
///
/// When enabled, some child wpf framework elements will not animate opacity changes.
/// Useful for improving performance during zoom.
- /// TODO DYN-8193 a future optimiztion if found to be neccesary is to modify the styles this flag controls
- /// to set visibility instead of opacity, this will likely lead to many fewers elements in the visual tree to
+ /// TODO DYN-8193 a future optimization if found to be necessary is to modify the styles this flag controls
+ /// to set visibility instead of opacity, this will likely lead to many fewer elements in the visual tree to
/// layout and render.
///
[JsonIgnore]
diff --git a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
index a64660908c0..37b6464498a 100644
--- a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
+++ b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs
@@ -11,6 +11,7 @@
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using System.Windows.Threading;
using Dynamo.Controls;
using Dynamo.Graph;
using Dynamo.Graph.Annotations;
@@ -149,6 +150,8 @@ private void RemoveViewModelsubscriptions(WorkspaceViewModel ViewModel)
ViewModel.Model.CurrentOffsetChanged -= vm_CurrentOffsetChanged;
DynamoSelection.Instance.Selection.CollectionChanged -= OnSelectionCollectionChanged;
infiniteGridView.DetachFromZoomBorder(zoomBorder);
+
+ currentRenderScale = -1;
}
///
@@ -640,9 +643,82 @@ void vm_CurrentOffsetChanged(object sender, EventArgs e)
void vm_ZoomChanged(object sender, EventArgs e)
{
- zoomBorder.SetZoom((e as ZoomEventArgs).Zoom);
- if (PortContextMenu.IsOpen) DestroyPortContextMenu();
+ var newZoomScale = (e as ZoomEventArgs).Zoom;
+ zoomBorder.SetZoom(newZoomScale);
+ if (PortContextMenu.IsOpen)
+ {
+ DestroyPortContextMenu();
+ }
+
+ CheckZoomScaleAndApplyNodeViewCache(newZoomScale);
+ }
+
+ #region NodeView_BitmapCache
+ private double currentRenderScale = -1;
+ const double maxZoomScaleForCache = .8;
+
+ private void CheckZoomScaleAndApplyNodeViewCache(double newZoomScale)
+ {
+ if (!ViewModel.StopNodeViewOpacityAnimations)
+ {
+ if (currentRenderScale > 0) // number of nodes reduced below max threshold
+ {
+ Dispatcher.BeginInvoke(ClearNodeViewCache, DispatcherPriority.Normal);
+ }
+
+ return;
+ }
+
+ if (newZoomScale > maxZoomScaleForCache)
+ {
+ if (currentRenderScale > 0)
+ {
+ Dispatcher.BeginInvoke(ClearNodeViewCache, DispatcherPriority.Normal);
+ }
+
+ return;
+ }
+
+ var newRenderScale = newZoomScale <= .2 ? .2 : newZoomScale <= .5 ? .5 : 1;
+
+ if (Math.Abs(newRenderScale - currentRenderScale) <= 0.01)
+ {
+ return;
+ }
+
+ currentRenderScale = newRenderScale;
+ Dispatcher.BeginInvoke(UpdateNodeViewCacheScale, DispatcherPriority.Normal);
+ }
+
+ private void ClearNodeViewCache()
+ {
+ var nodes = this.ChildrenOfType();
+ foreach (var node in nodes)
+ {
+ node.CacheMode = null;
+ }
+
+ currentRenderScale = -1;
+ }
+
+ private void UpdateNodeViewCacheScale()
+ {
+ var nodes = this.ChildrenOfType();
+ foreach (var node in nodes)
+ {
+ var cache = node.CacheMode as BitmapCache;
+ if (cache == null)
+ {
+ cache = new BitmapCache(currentRenderScale);
+ node.CacheMode = cache;
+ }
+ else
+ {
+ cache.RenderAtScale = currentRenderScale;
+ }
+ }
}
+ #endregion
void vm_ZoomAtViewportCenter(object sender, EventArgs e)
{