using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; using System.Xml; using System.Xml.Linq; using Tango.Core.Commands; using Tango.Core.DI; using Tango.FSE.Common; using Tango.FSE.Common.Notifications; using Tango.FSE.Common.Storage; using Tango.Settings; namespace Tango.FSE.Procedures.Dialogs { public class ProcedureDialogEditorViewVM : FSEDialogViewVM { private FileSystemWatcher _watcher; [TangoInject] private INotificationProvider NotificationProvider { get; set; } [TangoInject] private IStorageProvider StorageProvider { get; set; } private String _name; public String Name { get { return _name; } set { _name = value; RaisePropertyChangedAuto(); } } private String _xaml; public String Xaml { get { return _xaml; } set { _xaml = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(Content)); } } private FrameworkElement _content; public FrameworkElement Content { get { try { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.Write(Xaml); writer.Flush(); stream.Position = 0; FrameworkElement rootElement = (FrameworkElement)XamlReader.Load(stream); stream.Dispose(); HasError = false; Error = null; _content = rootElement; return rootElement; } catch (Exception ex) { Error = ex.Message; HasError = true; return _content; } } } private bool _hasError; public bool HasError { get { return _hasError; } set { _hasError = value; RaisePropertyChangedAuto(); } } private String _error; public String Error { get { return _error; } set { _error = value; RaisePropertyChangedAuto(); } } public RelayCommand OpenInBlendCommand { get; set; } public ProcedureDialogEditorViewVM() { TangoIOC.Default.Inject(this); OpenInBlendCommand = new RelayCommand(OpenInBlend); } private async void OpenInBlend() { if (_watcher != null) { return; } var settings = SettingsManager.Default.GetOrCreate(); String blendPath = settings.BlendPath; if (String.IsNullOrWhiteSpace(blendPath) || !File.Exists(blendPath)) { blendPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Blend.exe"; if (!File.Exists(blendPath)) { blendPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Blend.exe"; } } if (!File.Exists(blendPath)) { if (await NotificationProvider.ShowWarningQuestion("Could not locate Blend for Visual Studio on your computer.\nDo you wish to manually browse for it on your hard drive?", "BROWSE", "CANCEL")) { var r = await StorageProvider.OpenFile("Browse for Blend for Visual Studio", "Executables|*.exe"); if (!r.Confirmed) { return; } settings.BlendPath = r.SelectedItem; settings.Save(); blendPath = settings.BlendPath; } else { return; } } var tempFolder = TemporaryManager.CreateFolder(); var stream = Core.Helpers.EmbeddedResourceHelper.GetEmbeddedResourceStream("Tango.FSE.Procedures.Resources.procedure_dialog_template.zip"); stream.Position = 0; using (ZipArchive zip = new ZipArchive(stream)) { zip.ExtractToDirectory(tempFolder, true); } String mainWindowFile = Path.Combine(tempFolder, "MainWindow.xaml"); String mainWindowContent = File.ReadAllText(mainWindowFile); mainWindowContent = mainWindowContent.Replace("@", Xaml); File.WriteAllText(mainWindowFile, mainWindowContent); _watcher = new FileSystemWatcher(tempFolder); _watcher.Changed += (sender, e) => { if (e.ChangeType == WatcherChangeTypes.Changed) { try { String newContent = File.ReadAllText(e.FullPath); if (newContent.Contains(" x.Name.LocalName == "Window"); if (windowNode != null) { var firstChild = windowNode.Descendants().FirstOrDefault(); if (firstChild != null) { var newXaml = firstChild.ToString(); Xaml = newXaml; } } } } } catch (Exception ex) { Debug.WriteLine($"Error updating xaml from blend.\n{ex.ToString()}"); } } }; _watcher.EnableRaisingEvents = true; await Task.Factory.StartNew(() => { var p = Process.Start(blendPath, Path.Combine(tempFolder, "ProcedureDialog.csproj")); p.WaitForExit(); ClearWatcher(); }); } protected override void Accept() { ClearWatcher(); base.Accept(); } protected override void Cancel() { ClearWatcher(); base.Cancel(); } private void ClearWatcher() { _watcher?.Dispose(); _watcher = null; } } }