diff --git a/src/DynamoCoreWpf/Properties/Resources.Designer.cs b/src/DynamoCoreWpf/Properties/Resources.Designer.cs
index db8e4d9ea0f..54ba4ec8cfc 100644
--- a/src/DynamoCoreWpf/Properties/Resources.Designer.cs
+++ b/src/DynamoCoreWpf/Properties/Resources.Designer.cs
@@ -2683,6 +2683,33 @@ public static string EditWindowTitle {
}
}
+ ///
+ /// Looks up a localized string similar to Element Binding allows a two-way interaction between Dynamo and the host application like Revit or Civil3D where a user can select an element in the host document and have Dynamo "bind" that element to a node in the workspace..
+ ///
+ public static string ElementBindingDesc {
+ get {
+ return ResourceManager.GetString("ElementBindingDesc", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to A Save As command will create a workspace which is treated as a completely new file by Dynamo and existing element binding data will be lost. New element binding data will be created as normal as you run this file. Use the Save command instead if you wish to preserve element binding with the host document..
+ ///
+ public static string ElementBindingWarningMessage {
+ get {
+ return ResourceManager.GetString("ElementBindingWarningMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Element Binding Warning.
+ ///
+ public static string ElementBindingWarningTitle {
+ get {
+ return ResourceManager.GetString("ElementBindingWarningTitle", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to An error occurred when loading the application icon: {0}.
///
diff --git a/src/DynamoCoreWpf/Properties/Resources.en-US.resx b/src/DynamoCoreWpf/Properties/Resources.en-US.resx
index caac9cd1ebf..b6b9a256805 100644
--- a/src/DynamoCoreWpf/Properties/Resources.en-US.resx
+++ b/src/DynamoCoreWpf/Properties/Resources.en-US.resx
@@ -3651,4 +3651,13 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in
When toggled on, file names of exported images include date and time of export.
-
\ No newline at end of file
+
+ A Save As command will create a workspace which is treated as a completely new file by Dynamo and existing element binding data will be lost. New element binding data will be created as normal as you run this file. Use the Save command instead if you wish to preserve element binding with the host document.
+
+
+ Element Binding Warning
+
+
+ Element Binding allows a two-way interaction between Dynamo and the host application like Revit or Civil3D where a user can select an element in the host document and have Dynamo "bind" that element to a node in the workspace.
+
+
diff --git a/src/DynamoCoreWpf/Properties/Resources.resx b/src/DynamoCoreWpf/Properties/Resources.resx
index e094990be3f..20166f73c35 100644
--- a/src/DynamoCoreWpf/Properties/Resources.resx
+++ b/src/DynamoCoreWpf/Properties/Resources.resx
@@ -3638,4 +3638,13 @@ In certain complex graphs or host program scenarios, Automatic mode may cause in
When toggled on, file names of exported images include date and time of export.
-
\ No newline at end of file
+
+ A Save As command will create a workspace which is treated as a completely new file by Dynamo and existing element binding data will be lost. New element binding data will be created as normal as you run this file. Use the Save command instead if you wish to preserve element binding with the host document.
+
+
+ Element Binding Warning
+
+
+ Element Binding allows a two-way interaction between Dynamo and the host application like Revit or Civil3D where a user can select an element in the host document and have Dynamo "bind" that element to a node in the workspace.
+
+
diff --git a/src/DynamoCoreWpf/UI/Prompts/DynamoMessageBox.xaml b/src/DynamoCoreWpf/UI/Prompts/DynamoMessageBox.xaml
index 3bce7cdcf4d..cd7ba9d79b8 100644
--- a/src/DynamoCoreWpf/UI/Prompts/DynamoMessageBox.xaml
+++ b/src/DynamoCoreWpf/UI/Prompts/DynamoMessageBox.xaml
@@ -4,7 +4,7 @@
xmlns:p="clr-namespace:Dynamo.Wpf.Properties;assembly=DynamoCoreWpf"
xmlns:ui="clr-namespace:Dynamo.UI"
xmlns:localui="clr-namespace:Dynamo.Wpf.UI.GuidedTour"
- xmlns:w="clr-namespace:System.Windows;assembly=PresentationCore"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
Title="{x:Static p:Resources.GenericTaskDialogTitle}"
MinWidth="400"
MaxWidth="500"
@@ -98,6 +98,35 @@
Foreground="#3C3C3C"
Text="{Binding TitleText, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
+
+ /// A tooltip is shown on the message box when this is set to true and if
+ /// Tooltip is non-null and non-empty.
+ ///
+ public bool ShowTooltip { get; private set; }
+
+ ///
+ /// A tooltip is shown on the message box when this is set to a non-empty string
+ /// and ShowTooltip is true.
+ ///
+ public string Tooltip { get; private set; }
+
#endregion
///
@@ -97,6 +109,8 @@ public DynamoMessageBox()
{
InitializeComponent();
DataContext = this;
+ ShowTooltip = false;
+ ToolTip = "";
}
///
@@ -106,16 +120,19 @@ public DynamoMessageBox()
///
///
///
+ ///
///
public static MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button,
- MessageBoxImage icon)
+ MessageBoxImage icon, string tooltip = "")
{
var dynamoMessageBox = new DynamoMessageBox
{
BodyText = messageBoxText,
TitleText = caption,
MessageBoxButton = button,
- MessageBoxImage = icon
+ MessageBoxImage = icon,
+ ShowTooltip = !string.IsNullOrEmpty(tooltip),
+ Tooltip = tooltip
};
dynamoMessageBox.ConfigureButtons(button);
diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
index d412584d59a..307cd71115b 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
@@ -2087,10 +2087,13 @@ private void InternalSaveAs(string path, SaveContext saveContext, bool isBackup
{
try
{
- Model.Logger.Log(String.Format(Properties.Resources.SavingInProgress, path));
- CurrentSpaceViewModel.Save(path, isBackup, Model.EngineController, saveContext);
+ Model.Logger.Log(string.Format(Properties.Resources.SavingInProgress, path));
+ var hasSaved = CurrentSpaceViewModel.Save(path, isBackup, Model.EngineController, saveContext);
- if (!isBackup) AddToRecentFiles(path);
+ if (!isBackup && hasSaved)
+ {
+ AddToRecentFiles(path);
+ }
}
catch (Exception ex)
{
@@ -2151,8 +2154,10 @@ internal void SaveAs(Guid id, string path, bool isBackup = false, SaveContext sa
try
{
Model.Logger.Log(String.Format(Properties.Resources.SavingInProgress, path));
- Workspaces.Where(w => w.Model.Guid == id).FirstOrDefault().Save(path, isBackup, Model.EngineController, saveContext);
- if (!isBackup) AddToRecentFiles(path);
+ var hasSaved = Workspaces.FirstOrDefault(w => w.Model.Guid == id).Save(
+ path, isBackup, Model.EngineController, saveContext);
+
+ if (!isBackup && hasSaved) AddToRecentFiles(path);
}
catch (Exception ex)
{
diff --git a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
index 4c63be9050b..2d95e6378ec 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs
@@ -20,6 +20,7 @@
using Dynamo.Graph.Workspaces;
using Dynamo.Models;
using Dynamo.Selection;
+using Dynamo.UI.Prompts;
using Dynamo.Utilities;
using Dynamo.Wpf.ViewModels;
using Dynamo.Wpf.ViewModels.Core;
@@ -598,7 +599,7 @@ internal void ZoomOutInternal()
///
///
/// Thrown when the file path is null.
- internal void Save(string filePath, bool isBackup = false, EngineController engine = null, SaveContext saveContext = SaveContext.None)
+ internal bool Save(string filePath, bool isBackup = false, EngineController engine = null, SaveContext saveContext = SaveContext.None)
{
if (String.IsNullOrEmpty(filePath))
{
@@ -627,6 +628,23 @@ internal void Save(string filePath, bool isBackup = false, EngineController engi
{
// For intentional SaveAs either through UI or API calls, replace workspace elements' Guids and workspace Id
jo["Uuid"] = Guid.NewGuid().ToString();
+ if (jo["Bindings"] != null && jo["Bindings"].Any())
+ {
+ jo["Bindings"] = JToken.Parse("[]");
+
+ if (!DynamoModel.IsTestMode)
+ {
+ var result = DynamoMessageBox.Show(Wpf.Properties.Resources.ElementBindingWarningMessage,
+ Wpf.Properties.Resources.ElementBindingWarningTitle, MessageBoxButton.OKCancel,
+ MessageBoxImage.Warning, Wpf.Properties.Resources.ElementBindingDesc);
+
+ if (result == MessageBoxResult.Cancel)
+ {
+ return false;
+ }
+ }
+ }
+
saveContent = GuidUtility.UpdateWorkspaceGUIDs(jo.ToString());
}
else
@@ -656,6 +674,8 @@ internal void Save(string filePath, bool isBackup = false, EngineController engi
Debug.WriteLine(ex.Message + " : " + ex.StackTrace);
throw (ex);
}
+
+ return true;
}
///
/// This function appends view block to the model json
diff --git a/test/DynamoCoreWpfTests/DynamoViewTests.cs b/test/DynamoCoreWpfTests/DynamoViewTests.cs
index 706448ba3d9..3ca828479a6 100644
--- a/test/DynamoCoreWpfTests/DynamoViewTests.cs
+++ b/test/DynamoCoreWpfTests/DynamoViewTests.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -21,6 +22,7 @@
using Dynamo.Wpf.ViewModels.Core;
using Dynamo.Wpf.Views;
using DynamoCoreWpfTests.Utility;
+using Newtonsoft.Json.Linq;
using NUnit.Framework;
using SharpDX.DXGI;
@@ -126,6 +128,49 @@ public void OpeningWorkspaceWithTclsrustWarning()
DynamoModel.IsTestMode = true;
}
+ [Test]
+ public void ElementBinding_SaveAs()
+ {
+ var prebindingPathInTestDir = @"core\callsite\trace_test-prebinding.dyn";
+ var prebindingPath = Path.Combine(GetTestDirectory(ExecutingDirectory), prebindingPathInTestDir);
+
+ var pathInTestsDir = @"core\callsite\trace_test.dyn";
+ var filePath = Path.Combine(GetTestDirectory(ExecutingDirectory), pathInTestsDir);
+
+ // Always start with a fresh workspace with no binding data for this test.
+ File.Copy(prebindingPath, filePath);
+ OpenAndRun(pathInTestsDir);
+
+ // Assert that the node doesn't have trace data the first time it's run.
+ var hasTraceData = Model.CurrentWorkspace.Nodes.FirstOrDefault(x =>
+ x.Name == "IncrementerTracedClass.WasCreatedWithTrace");
+ Assert.AreEqual(false, hasTraceData.CachedValue.Data);
+
+ // Saving the workspace after a run serializes trace data to the DYN.
+ ViewModel.SaveCommand.Execute(null);
+
+ DynamoUtilities.PathHelper.isValidJson(filePath, out string fileContents, out Exception ex);
+ var obj = DSCore.Data.ParseJSON(fileContents) as Dictionary;
+ Assert.AreEqual(1, (obj["Bindings"] as IEnumerable