WorkflowDesigner.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / WorkflowDesigner.cs / 1546523 / WorkflowDesigner.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

 
namespace System.Activities.Presentation
{ 
    using System; 
    using System.Activities.Debugger;
    using System.Activities.Presentation.Debug; 
    using System.Activities.Presentation.Documents;
    using System.Activities.Presentation.Internal.PropertyEditing;
    using System.Activities.Presentation.Internal.PropertyEditing.Metadata;
    using System.Activities.Presentation.Internal.PropertyEditing.Resources; 
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.Validation; 
    using System.Activities.Presentation.View; 
    using System.Activities.Presentation.Xaml;
    using System.Activities.XamlIntegration; 
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.IO; 
    using System.Runtime; 
    using System.Text;
    using System.Windows; 
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Interop;
    using System.Windows.Markup; 
    using System.Windows.Threading;
    using System.Xaml; 
    using System.Xml; 
    using System.Linq;
    using System.Activities.Presentation.Hosting; 

    // This is the workflow designer context class.
    // it provides two views the primary workflow view in View property and the property browser view in the
    // propertyInspectorView property. 
    // Load takes a objects instance or Xaml ( in the future) to load the designer from
    public class WorkflowDesigner 
    { 
        EditingContext context;
        ModelTreeManager modelTreeManager; 
        Grid view;
        PropertyInspector propertyInspector;
        string text;
        string loadedFile; 
        DebuggerService debuggerService;
        UndoEngine undoEngine; 
        ViewManager viewManager; 
        ValidationService validationService;
        DesignerPerfEventProvider perfEventProvider; 
        bool isLoaded = false;
        bool isModelChanged = false;

        IXamlLoadErrorService xamlLoadErrorService; 
        WorkflowDesignerXamlSchemaContext workflowDesignerXamlSchemaContext;
 
 
        public event TextChangedEventHandler TextChanged;
        public event EventHandler ModelChanged; 

        internal class PreviewLoadEventArgs : EventArgs
        {
            object instance; 
            EditingContext context;
 
            public PreviewLoadEventArgs(object instance, EditingContext context) 
            {
                this.instance = instance; 
                this.context = context;
            }

            public object Instance 
            {
                get { return this.instance; } 
            } 

            public EditingContext Context 
            {
                get { return this.context; }
            }
        } 
        internal event EventHandler PreviewLoad;
 
        [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.InitializeReferenceTypeStaticFieldsInline, 
            Justification = "The static constructor is required to initialize the PropertyInspector metadata.")]
        static WorkflowDesigner() 
        {
            InitializePropertyInspectorMetadata();
            DesignerMetadata metaData = new DesignerMetadata();
            metaData.Register(); 
        }
 
        public WorkflowDesigner() 
        {
            // create our perf trace provider first 
            this.perfEventProvider = new DesignerPerfEventProvider();

            this.context = new EditingContext();
            this.context.Items.SetValue(new ReadOnlyState { IsReadOnly = false }); 
            this.view = new Grid();
            this.view.Focusable = false; 
            this.propertyInspector = new PropertyInspector(); 
            this.propertyInspector.DesignerContextItemManager = this.context.Items;
            PropertyInspectorMergedResources.PropertyInspectorResources = this.propertyInspector.Resources; 
            WorkflowDesignerColors.FontResources = this.propertyInspector.Resources;
            //add the resource dictionary to application resource so every component could reference it
            if (Application.Current == null)
            { 
                //create an applicatio if it doesn't exist, make sure it will not shutdown after windows being shut down
                Application app = new Application(); 
                app.ShutdownMode = ShutdownMode.OnExplicitShutdown; 
            }
            Fx.Assert(Application.Current != null, "Application and resources must be there"); 
            Application.Current.Resources.MergedDictionaries.Add(this.propertyInspector.Resources);

            AttachedPropertiesService propertiesService = new AttachedPropertiesService();
            this.context.Services.Publish(typeof(AttachedPropertiesService), propertiesService); 

            undoEngine = new UndoEngine(context); 
            this.context.Services.Publish(typeof(UndoEngine), undoEngine); 
            undoEngine.ExecuteUndo += new EventHandler(OnExecuteUndo);
 
            this.context.Services.Publish(this.ValidationService);
            this.context.Services.Publish(this.perfEventProvider);
            this.context.Services.Publish(new FeatureManager(this.context));
 
            InitializePropertyInspectorResources();
            InitializePropertyInspectorCommandHandling(); 
 
            this.Context.Items.Subscribe(delegate(ErrorItem errorItem)
            { 
                ErrorView errorView = new ErrorView();
                errorView.Message = errorItem.Message;
                errorView.Details = errorItem.Details;
                this.view.Children.Clear(); 
                this.view.Children.Add(errorView);
            } 
                ); 

            this.context.Items.Subscribe(new SubscribeContextCallback(OnReadonlyStateChanged)); 

            this.context.Services.Subscribe(s => this.xamlLoadErrorService = s);

            this.PreviewLoad += VisualBasicSettingsHandler.PreviewLoadRoot; 
            this.view.Loaded += (s, e) =>
            { 
                //when view is loaded, check if user did provide his own WindowHelperService - if not, provide a default one 
                if (!this.context.Services.Contains())
                { 
                    IntPtr hWND = IntPtr.Zero;
                    Window ownerWindow = Window.GetWindow(this.view);
                    if (null != ownerWindow)
                    { 
                        WindowInteropHelper helper = new WindowInteropHelper(ownerWindow);
                        hWND = helper.Handle; 
                    } 
                    this.Context.Services.Publish(new WindowHelperService(hWND));
                } 
                WindowHelperService whs = this.context.Services.GetService();
                whs.View = this.view;

                //check if workflow command extension item is available - if not, provide default one 
                if (!this.context.Items.Contains())
                { 
                    WorkflowCommandExtensionItem item = new WorkflowCommandExtensionItem(new DefaultCommandExtensionCallback()); 
                    this.context.Items.SetValue(item);
                } 

                ComponentDispatcher.EnterThreadModal += new EventHandler(ComponentDispatcher_EnterThreadModal);
                ComponentDispatcher.LeaveThreadModal += new EventHandler(ComponentDispatcher_LeaveThreadModal);
            }; 

            this.view.Unloaded += (s, e) => 
            { 
                ComponentDispatcher.EnterThreadModal -= new EventHandler(ComponentDispatcher_EnterThreadModal);
                ComponentDispatcher.LeaveThreadModal -= new EventHandler(ComponentDispatcher_LeaveThreadModal); 
            };

            this.view.IsKeyboardFocusWithinChanged += (s, e) =>
            { 
                // The ModelTreeManager is null when there is an active ErrorItem.
                // We have nothing to write to text in this case. 
                if (this.modelTreeManager != null && (bool)e.NewValue == false) 
                {
                    if ((FocusManager.GetFocusedElement(this.view) as TextBox) != null) 
                    {
                        FocusManager.SetFocusedElement(this.view, null);
                        this.NotifyModelChanged();
                    } 
                }
            }; 
        } 

        void ComponentDispatcher_EnterThreadModal(object sender, EventArgs e) 
        {
            IModalService modalService = Context.Services.GetService();
            if (modalService != null)
            { 
                modalService.SetModalState(true);
            } 
        } 

        void ComponentDispatcher_LeaveThreadModal(object sender, EventArgs e) 
        {
            IModalService modalService = Context.Services.GetService();
            if (modalService != null)
            { 
                modalService.SetModalState(false);
            } 
        } 

        WorkflowDesignerXamlSchemaContext XamlSchemaContext 
        {
            get
            {
                if (this.workflowDesignerXamlSchemaContext == null) 
                {
                    this.workflowDesignerXamlSchemaContext = new WorkflowDesignerXamlSchemaContext(GetLocalAssemblyName(), this.Context); 
 
                }
 
                return this.workflowDesignerXamlSchemaContext;
            }
        }
 
        string GetLocalAssemblyName()
        { 
            AssemblyContextControlItem assemblyItem = this.Context.Items.GetValue(); 
            return assemblyItem != null && assemblyItem.LocalAssemblyName != null ? assemblyItem.LocalAssemblyName.Name : null;
        } 

        void OnExecuteUndo(object sender, UndoUnitEventArgs e)
        {
            // If an action had caused the errorview to be shown, and undo was executed after that 
            // try to put back the viewmanagerview back as the rootview of the designer.
            // may be the undo might help recover from the problem. 
            if (!this.view.Children.Contains((UIElement)this.viewManager.View)) 
            {
                this.view.Children.Clear(); 
                this.view.Children.Add((UIElement)this.viewManager.View);

                // Clear out the error condition
                ErrorItem errorItem = this.context.Items.GetValue(); 
                errorItem.Message = null;
                errorItem.Details = null; 
            } 
        }
 
        internal ValidationService ValidationService
        {
            get
            { 
                if (this.validationService == null)
                { 
                    this.validationService = new ValidationService(this.context); 
                    this.validationService.ErrorsMarked += ArgumentFixer.UpdateInvalidArgumentsIfNecessary;
                } 

                return this.validationService;
            }
        } 

        public UIElement View 
        { 
            get
            { 
                return this.view;
            }
        }
 
        public UIElement PropertyInspectorView
        { 
            get 
            {
                return this.propertyInspector; 
            }
        }
        public EditingContext Context
        { 
            get
            { 
                return this.context; 
            }
        } 

        public ContextMenu ContextMenu
        {
            get 
            {
                if (null != this.context) 
                { 
                    DesignerView designerView = this.context.Services.GetService();
                    if (null != designerView) 
                    {
                        return designerView.ContextMenu;
                    }
                } 
                return null;
            } 
        } 

        public string Text 
        {
            get { return this.text; }
            set { this.text = value; }
        } 

        [SuppressMessage(FxCop.Category.Design, "CA1044:PropertiesShouldNotBeWriteOnly", 
            Justification = "The host just sets this property for the designer to know which colors to display.")] 
        public string PropertyInspectorFontAndColorData
        { 
            set
            {
                StringReader stringReader = new StringReader(value);
                XmlReader xmlReader = XmlReader.Create(stringReader); 
                Hashtable fontAndColorDictionary = (Hashtable)System.Windows.Markup.XamlReader.Load(xmlReader);
                foreach (string key in fontAndColorDictionary.Keys) 
                { 
                    if (this.propertyInspector.Resources.Contains(key))
                    { 
                        this.propertyInspector.Resources[key] = fontAndColorDictionary[key];
                    }
                    else
                    { 
                        this.propertyInspector.Resources.Add(key, fontAndColorDictionary[key]);
                    } 
                    WorkflowDesignerColors.ColorServiceColors[key] = fontAndColorDictionary[key]; 
                }
                Application.Current.Resources.MergedDictionaries.Add(this.propertyInspector.Resources); 
            }
        }

        public IDesignerDebugView DebugManagerView 
        {
            get 
            { 
                return this.DebuggerService;
            } 
        }

        DebuggerService DebuggerService
        { 
            get
            { 
                if (this.debuggerService == null) 
                {
                    this.debuggerService = new DebuggerService(this.context); 
                    this.context.Services.Publish(this.debuggerService);
                }
                return this.debuggerService;
            } 

        } 
 

        public bool IsInErrorState() 
        {
            ErrorItem errorItem = this.context.Items.GetValue();
            return errorItem.Message != null && errorItem.Details != null ? true : false;
        } 

        // Load using Xaml. 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes, 
            Justification = "Deserializer might throw if it fails to deserialize. Catching all exceptions to avoid VS Crash.")]
        [SuppressMessage("Reliability", "Reliability108", 
            Justification = "Deserializer might throw if it fails to deserialize. Catching all exceptions to avoid VS crash.")]
        public void Load()
        {
            this.perfEventProvider.WorkflowDesignerLoadStart(); 
            if (!string.IsNullOrEmpty(this.text))
            { 
                try 
                {
                    this.perfEventProvider.WorkflowDesignerDeserializeStart(); 

                    IList loadErrors;
                    object deserializedObject = DeserializeString(this.text, out loadErrors);
 
                    this.perfEventProvider.WorkflowDesignerDeserializeEnd();
 
                    if (deserializedObject != null) 
                    {
                        this.Load(deserializedObject); 
                        this.ValidationService.ValidateWorkflow(ValidationReason.Load);
                    }
                    else
                    { 
                        StringBuilder details = new StringBuilder();
                        foreach (XamlLoadErrorInfo error in loadErrors) 
                        { 
                            details.AppendLine(error.Message);
                        } 
                        this.Context.Items.SetValue(new ErrorItem() { Message = SR.SeeErrorWindow, Details = details.ToString() });
                    }
                    if (loadErrors != null)
                    { 
                        RaiseLoadErrors(loadErrors);
                    } 
                    this.isModelChanged = false; 
                }
                catch (Exception e) 
                {
                    this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() });
                    RaiseLoadError(e);
                } 
            }
            else 
            { 
                this.Context.Items.SetValue(new ErrorItem() { Message = string.Empty, Details = string.Empty });
            } 
            this.perfEventProvider.WorkflowDesignerLoadComplete();
        }

        public void Load(string fileName) 
        {
            IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService(); 
            if (documentPersistenceService != null) 
            {
                this.Load(documentPersistenceService.Load(fileName)); 
            }
            else
            {
                using (StreamReader fileStream = new StreamReader(fileName)) 
                {
                    this.loadedFile = fileName; 
                    WorkflowFileItem fileItem = new WorkflowFileItem(); 
                    fileItem.LoadedFile = fileName;
                    this.context.Items.SetValue(fileItem); 
                    this.Text = fileStream.ReadToEnd();
                    this.Load();
                }
            } 
            if (this.debuggerService != null && !this.IsInErrorState())
            { 
                this.UpdateSourceLocationMappingInDebuggerService(); 
            }
        } 


        // This supports  loading objects instead of xaml into the designer
        public void Load(object instance) 
        {
            if (isLoaded) 
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowDesignerLoadShouldBeCalledOnlyOnce));
            } 

            isLoaded = true;

            if (instance == null) 
            {
                throw FxTrace.Exception.AsError(new ArgumentNullException("instance")); 
            } 

            if (this.PreviewLoad != null) 
            {
                this.PreviewLoad(this, new PreviewLoadEventArgs(instance, this.context));
            }
 
            modelTreeManager = new ModelTreeManager(this.context);
            modelTreeManager.Load(instance); 
            this.context.Services.Publish(typeof(ModelTreeManager), modelTreeManager); 

            viewManager = GetViewManager(this.modelTreeManager.Root); 
            view.Children.Add((UIElement)viewManager.View);
            modelTreeManager.EditingScopeCompleted += new EventHandler(OnEditingScopeCompleted);

 

            this.view.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, 
                             new Action(() => { this.perfEventProvider.WorkflowDesignerApplicationIdleAfterLoad(); })); 

            //Subscribe to the ViewStateChanged event of ViewStateService to show document dirty. It would be published in the call to GetViewManager(). 
            WorkflowViewStateService wfViewStateService = this.Context.Services.GetService(typeof(ViewStateService)) as WorkflowViewStateService;
            if (wfViewStateService != null)
            {
                wfViewStateService.UndoableViewStateChanged += new ViewStateChangedEventHandler(OnViewStateChanged); 
            }
            this.isModelChanged = false; 
        } 

 
        void OnViewStateChanged(object sender, ViewStateChangedEventArgs e)
        {
            NotifyModelChanged();
        } 

        void OnEditingScopeCompleted(object sender, EditingScopeEventArgs e) 
        { 
            if (e.EditingScope.HasEffectiveChanges)
            { 
                NotifyModelChanged();
                if (!this.modelTreeManager.RedoUndoInProgress
                    && undoEngine != null
                    && !e.EditingScope.SuppressUndo) 
                {
                    undoEngine.AddUndoUnit(new EditingScopeUndoUnit(this, this.modelTreeManager, e.EditingScope)); 
                } 
                if (e.EditingScope.HasModelChanges)
                { 
                    this.ValidationService.ValidateWorkflow(ValidationReason.ModelChange);
                }
            }
        } 

        public void Save(string fileName) 
        { 
            this.isModelChanged = true; // ensure flushing any viewstate changes that does not imply model changed.
            Flush(); 
            using (StreamWriter fileStreamWriter = new StreamWriter(fileName, false, Encoding.UTF8))
            {
                fileStreamWriter.Write(this.Text);
                fileStreamWriter.Flush(); 
            }
 
            this.ValidationService.ValidateWorkflow(ValidationReason.Save); 

            if (this.debuggerService != null) 
            {
                try
                {
                    this.CollectSourceLocationMapping(); 
                }
                catch (Exception ex) 
                { 
                    System.Diagnostics.Trace.WriteLine("Save operation completed, however problem encountered during reading it back.\nError: " + ex.Message);
                    throw; 
                }
            }

        } 

        public void Flush() 
        { 
            if (this.modelTreeManager == null)
            { 
                // It's possible for modelTreeManager to be null if Load is called but the xaml file being loaded is invalid.
                // We only want to throw exception if Load hasn't been called yet.
                if (IsInErrorState() == false)
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowDesignerLoadShouldBeCalledFirst));
                } 
            } 
            else
            { 
                this.FlushEdits();
                IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService();
                if (documentPersistenceService != null)
                { 
                    documentPersistenceService.Flush(this.modelTreeManager.Root.GetCurrentValue());
                } 
                else 
                {
                    this.WriteModelToText(); 
                }
            }
        }
 
        void FlushEdits()
        { 
            UIElement oldFocus = null; 
            //check if property grid has keyboard focus within, if yes - get focused control
            if (null != this.propertyInspector && this.propertyInspector.IsKeyboardFocusWithin) 
            {
                oldFocus = FocusManager.GetFocusedElement(this.propertyInspector) as UIElement;
            }
            //check if view has keyboard focus within, if yes - get focused control 
            if (null != this.view && this.view.IsKeyboardFocusWithin)
            { 
                oldFocus = FocusManager.GetFocusedElement(this.view) as UIElement; 
            }
            if (null != oldFocus) 
            {
                RoutedCommand cmd = DesignerView.CommitCommand as RoutedCommand;
                if (cmd != null)
                { 
                    cmd.Execute(null, oldFocus);
                } 
            } 

            //commit changes within arguments and variables editor 
            var designerView = this.Context.Services.GetService();
            if (null != designerView)
            {
                if (null != designerView.arguments1) 
                {
                    DataGridHelper.CommitPendingEdits(designerView.arguments1.argumentsDataGrid); 
                } 
                if (null != designerView.variables1)
                { 
                    DataGridHelper.CommitPendingEdits(designerView.variables1.variableDataGrid);
                }
            }
        } 

        void InitializePropertyInspectorCommandHandling() 
        { 
        }
 
        void InitializePropertyInspectorResources()
        {
            this.propertyInspector.Resources.MergedDictionaries.Add(PropertyInspectorResources.GetResources());
        } 

        static void InitializePropertyInspectorMetadata() 
        { 
            PropertyInspectorMetadata.Initialize();
        } 

        ViewManager GetViewManager(ModelItem modelItem)
        {
            Fx.Assert(modelItem != null, "modelItem cannot be null"); 
            ViewManager viewManager = null;
            // First we look for a ViewManagerAttribute. for example a ServiceContractRoot tag, could use 
            // use its own view manager if it wanted to . 
            ViewManagerAttribute viewManagerAttribute = TypeDescriptor.GetAttributes(modelItem.ItemType)[typeof(ViewManagerAttribute)] as ViewManagerAttribute;
            if (viewManagerAttribute != null && viewManagerAttribute.ViewManagerType != null) 
            {
                viewManager = (ViewManager)Activator.CreateInstance(viewManagerAttribute.ViewManagerType);

            } 
            // If no viewmanager attribute is found we default to the workflowviewmanager
            if (viewManager == null) 
            { 
                viewManager = new WorkflowViewManager();
            } 
            viewManager.Initialize(this.context);
            return viewManager;
        }
 
        void NotifyModelChanged()   // Notify text is going to changed
        { 
            IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService(); 
            if (documentPersistenceService != null)
            { 
                documentPersistenceService.OnModelChanged(this.modelTreeManager.Root.GetCurrentValue());
            }
            else
            { 
                this.isModelChanged = true;
                if (this.ModelChanged != null) 
                { 
                    this.ModelChanged.Invoke(this, null);
                } 
            }
        }

 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes,
            Justification = "Serializer might throw if it fails to serialize. Catching all exceptions to avoid VS Crash.")] 
        [SuppressMessage("Reliability", "Reliability108", 
            Justification = "Serializer might throw if it fails to serialize. Catching all exceptions to avoid VS crash.")]
        void WriteModelToText() 
        {
            this.perfEventProvider.WorkflowDesignerSerializeStart();
            object rootModelObject = this.modelTreeManager.Root.GetCurrentValue();
            // if we are serializing a activity schema type, remove the namespace in the Name property. 
            ActivityBuilder activityBuilderType = rootModelObject as ActivityBuilder;
 
            // now try to serialize 
            try
            { 
                string newText = SerializeToString(rootModelObject);
                if (string.IsNullOrEmpty(this.Text) ||
                    (this.isModelChanged && !string.Equals(newText, this.Text, StringComparison.Ordinal)))
                { 
                    this.Text = newText;
                    if (this.TextChanged != null) 
                    { 
                        this.TextChanged.Invoke(this, null);
                    } 
                }
                this.isModelChanged = false;
            }
            catch (Exception e) 
            {
                this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() }); 
            } 
            this.perfEventProvider.WorkflowDesignerSerializeEnd();
        } 

        internal object DeserializeString(string text)
        {
            IList loadErrors; 
            return DeserializeString(text, out loadErrors);
        } 
 
        internal object DeserializeString(string text, out IList loadErrors)
        { 
            try
            {
                return DeserializeString(text, false, out loadErrors);
            } 
            catch (XamlObjectWriterException)
            { 
                // Fall back to error-tolerant path. We don't do this by default for perf reasons. 
                return DeserializeString(text, true, out loadErrors);
            } 
        }

        internal object DeserializeString(string text, bool errorTolerant, out IList loadErrors)
        { 
            using (XamlXmlReader xamlXmlReader =
                new XamlXmlReader(XmlReader.Create(new StringReader(text)), 
                        this.XamlSchemaContext, 
                        new XamlXmlReaderSettings { ProvideLineInfo = true }))
            { 
                using (XamlDebuggerXmlReader debuggerReader = new XamlDebuggerXmlReader(xamlXmlReader, new StringReader(text)))
                {
                    using (System.Xaml.XamlReader activityBuilderReader = ActivityXamlServices.CreateBuilderReader(debuggerReader))
                    { 
                        if (errorTolerant)
                        { 
                            ErrorTolerantObjectWriter tolerantWriter = new ErrorTolerantObjectWriter(activityBuilderReader.SchemaContext); 
                            tolerantWriter.LocalAssemblyName = GetLocalAssemblyName();
                            XamlServices.Transform(activityBuilderReader, tolerantWriter); 
                            loadErrors = tolerantWriter.LoadErrors;
                            object result = tolerantWriter.Result;
                            ErrorActivity.SetHasErrorActivities(result, true);
                            return result; 
                        }
                        else 
                        { 
                            loadErrors = null;
                            XamlObjectWriter objectWriter = new XamlObjectWriter(activityBuilderReader.SchemaContext); 
                            if (this.XamlSchemaContext.HasLocalAssembly)
                            {
                                CopyNamespacesAndAddLocalAssembly(activityBuilderReader, objectWriter);
                            } 
                            XamlServices.Transform(activityBuilderReader, objectWriter);
                            return objectWriter.Result; 
                        } 
                    }
                } 
            }
        }

        internal string SerializeToString(object obj) 
        {
            TextWriter textWriter = new StringWriter(CultureInfo.InvariantCulture); 
 
            WorkflowDesignerXamlSchemaContext schemaContext = obj is ActivityBuilder ? this.XamlSchemaContext : new WorkflowDesignerXamlSchemaContext(null);
 
            using (textWriter)
            {
                using (System.Xaml.XamlWriter writer =
                    ActivityXamlServices.CreateBuilderWriter(new DesignTimeXamlWriter(textWriter, 
                            schemaContext)))
                { 
                    XamlObjectReader objectReader = new XamlObjectReader(obj, schemaContext); 
                    if (ErrorActivity.GetHasErrorActivities(obj))
                    { 
                        ErrorTolerantObjectWriter.TransformAndStripErrors(objectReader, writer);
                    }
                    else
                    { 
                        XamlServices.Transform(objectReader, writer);
 
                    } 
                }
            } 
            return textWriter.ToString();
        }

        // Copy the root namespaces from a reader to a writer. 
        // DesignTimeXamlWriter follows proper XAML convention by omitting the assembly name from
        // clr-namespaces in the local assembly. However, VB Expressions aren't local-assembly-aware, 
        // and require an assembly name. So for every clr-namespace with no assembly name, we add an 
        // additional namespace record with an assembly name, to support VB.
        // We only do this at the root level, since the designer only writes out namespaces at the root level. 
        void CopyNamespacesAndAddLocalAssembly(System.Xaml.XamlReader activityBuilderReader, System.Xaml.XamlWriter objectWriter)
        {
            // Designer loads alwas provide line info
            IXamlLineInfo lineInfo = (IXamlLineInfo)activityBuilderReader; 
            IXamlLineInfoConsumer lineInfoConsumer = (IXamlLineInfoConsumer)objectWriter;
            HashSet definedPrefixes = new HashSet(); 
            List localAsmNamespaces = null; 

            while (activityBuilderReader.Read()) 
            {
                lineInfoConsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
                if (activityBuilderReader.NodeType == XamlNodeType.NamespaceDeclaration)
                { 
                    definedPrefixes.Add(activityBuilderReader.Namespace.Prefix);
                    if (this.XamlSchemaContext.IsClrNamespaceWithNoAssembly(activityBuilderReader.Namespace.Namespace)) 
                    { 
                        if (localAsmNamespaces == null)
                        { 
                            localAsmNamespaces = new List();
                        }
                        localAsmNamespaces.Add(activityBuilderReader.Namespace);
                    } 
                    objectWriter.WriteNode(activityBuilderReader);
                } 
                else 
                {
                    if (localAsmNamespaces != null) 
                    {
                        foreach (NamespaceDeclaration ns in localAsmNamespaces)
                        {
                            string prefix = null; 
                            int i = 0;
                            do 
                            { 
                                i++;
                                prefix = ns.Prefix + i.ToString(CultureInfo.InvariantCulture); 
                            }
                            while (definedPrefixes.Contains(prefix));
                            string fullNs = this.XamlSchemaContext.AddLocalAssembly(ns.Namespace);
                            objectWriter.WriteNamespace(new NamespaceDeclaration(fullNs, prefix)); 
                            definedPrefixes.Add(prefix);
                        } 
                    } 
                    objectWriter.WriteNode(activityBuilderReader);
                    return; 
                }
            }
        }
 
        void OnReadonlyStateChanged(ReadOnlyState state)
        { 
            if (null != this.propertyInspector) 
            {
                this.propertyInspector.IsReadOnly = state.IsReadOnly; 
            }
        }

        void UpdateSourceLocationMappingInDebuggerService() 
        {
            object rootInstance = this.GetRootInstance(); 
            Dictionary sourceLocationMapping = new Dictionary(); 

            if (rootInstance != null) 
            {
                Activity documentRootElement = GetRootWorkflowElement(rootInstance);
                if (documentRootElement != null)
                { 
                    this.CollectMappingFromSourceLocationProvider(documentRootElement, documentRootElement, sourceLocationMapping,
                        this.Context.Items.GetValue().LoadedFile); 
                } 
            }
 
            // Notify the DebuggerService of the new sourceLocationMapping.
            // When rootInstance == null, it'll just reset the mapping.
            if (this.debuggerService != null)
            { 
                this.debuggerService.UpdateSourceLocations(sourceLocationMapping);
            } 
        } 

        void CollectSourceLocationMapping() 
        {
            //Regenerate new SourceLocation mapping.
            object deserializedObject = this.DeserializeString(this.Text);
            if (deserializedObject != null) 
            {
                Activity documentRootElement = GetRootWorkflowElement(this.GetRootInstance()); 
                Activity deserializedRootElement = GetRootWorkflowElement(deserializedObject); 

                Dictionary sourceLocationMapping = new Dictionary(); 
                if (documentRootElement != null && deserializedRootElement != null)
                {
                    string loadedFile = this.Context.Items.GetValue().LoadedFile;
                    this.CollectMappingFromSourceLocationProvider(documentRootElement, deserializedRootElement, sourceLocationMapping, loadedFile); 
                }
 
                //Notify the DebuggerService of the Save so that it can recompute its cache. 
                DebuggerService debuggerService = this.DebugManagerView as DebuggerService;
                if (debuggerService != null) 
                {
                    debuggerService.UpdateSourceLocations(sourceLocationMapping);
                }
            } 
            else
            { 
                Fx.Assert("Unable to deserialize Xaml representation."); 
            }
        } 

        void CollectMappingFromSourceLocationProvider(Activity documentRootElement, Activity deserializedRootElement, Dictionary sourceLocationMapping, string loadedFile)
        {
            try 
            {
                SourceLocationProvider.CollectMapping(documentRootElement, deserializedRootElement, sourceLocationMapping, loadedFile); 
            } 
            catch (System.Exception ex)
            { 
                System.Diagnostics.Debug.WriteLine("Exception caught, debugger functionalities may be limited: " + ex.Message);
                if (Fx.IsFatal(ex))
                {
                    throw; 
                }
            } 
        } 

        // Get root Activity.  Currently only handle when the object is ActivityBuilder or Activity. 
        // May return null if it does not know how to get the root activity.
        static Activity GetRootWorkflowElement(object rootModelObject)
        {
            Fx.Assert(rootModelObject != null, "Cannot pass null as rootModelObject"); 

            Activity rootWorkflowElement; 
            IDebuggableWorkflowTree debuggableWorkflowTree = rootModelObject as IDebuggableWorkflowTree; 
            if (debuggableWorkflowTree != null)
            { 
                rootWorkflowElement = debuggableWorkflowTree.GetWorkflowRoot();
            }
            else // Loose xaml case.
            { 
                rootWorkflowElement = rootModelObject as Activity;
            } 
            return rootWorkflowElement; 
        }
 
        object GetRootInstance()
        {
            return this.modelTreeManager.Root.GetCurrentValue();
        } 

        void RaiseLoadError(Exception e) 
        { 
            if (this.xamlLoadErrorService != null)
            { 
                XamlLoadErrorInfo errorInfo = null;
                XamlException xamlEx = e as XamlException;
                if (xamlEx != null)
                { 
                    errorInfo = new XamlLoadErrorInfo(xamlEx.Message, xamlEx.LineNumber, xamlEx.LinePosition);
                } 
                else 
                {
                    XmlException xmlEx = e as XmlException; 
                    if (xmlEx != null)
                    {
                        errorInfo = new XamlLoadErrorInfo(xmlEx.Message, xmlEx.LineNumber, xmlEx.LinePosition);
                    } 
                }
                if (errorInfo != null) 
                { 
                    var errors = new XamlLoadErrorInfo[] { errorInfo };
                    xamlLoadErrorService.ShowXamlLoadErrors(errors); 
                }
            }
        }
 
        void RaiseLoadErrors(IList loadErrors)
        { 
            if (this.xamlLoadErrorService != null) 
            {
                this.xamlLoadErrorService.ShowXamlLoadErrors(loadErrors); 
            }
        }

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

 
namespace System.Activities.Presentation
{ 
    using System; 
    using System.Activities.Debugger;
    using System.Activities.Presentation.Debug; 
    using System.Activities.Presentation.Documents;
    using System.Activities.Presentation.Internal.PropertyEditing;
    using System.Activities.Presentation.Internal.PropertyEditing.Metadata;
    using System.Activities.Presentation.Internal.PropertyEditing.Resources; 
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.Validation; 
    using System.Activities.Presentation.View; 
    using System.Activities.Presentation.Xaml;
    using System.Activities.XamlIntegration; 
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.IO; 
    using System.Runtime; 
    using System.Text;
    using System.Windows; 
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Interop;
    using System.Windows.Markup; 
    using System.Windows.Threading;
    using System.Xaml; 
    using System.Xml; 
    using System.Linq;
    using System.Activities.Presentation.Hosting; 

    // This is the workflow designer context class.
    // it provides two views the primary workflow view in View property and the property browser view in the
    // propertyInspectorView property. 
    // Load takes a objects instance or Xaml ( in the future) to load the designer from
    public class WorkflowDesigner 
    { 
        EditingContext context;
        ModelTreeManager modelTreeManager; 
        Grid view;
        PropertyInspector propertyInspector;
        string text;
        string loadedFile; 
        DebuggerService debuggerService;
        UndoEngine undoEngine; 
        ViewManager viewManager; 
        ValidationService validationService;
        DesignerPerfEventProvider perfEventProvider; 
        bool isLoaded = false;
        bool isModelChanged = false;

        IXamlLoadErrorService xamlLoadErrorService; 
        WorkflowDesignerXamlSchemaContext workflowDesignerXamlSchemaContext;
 
 
        public event TextChangedEventHandler TextChanged;
        public event EventHandler ModelChanged; 

        internal class PreviewLoadEventArgs : EventArgs
        {
            object instance; 
            EditingContext context;
 
            public PreviewLoadEventArgs(object instance, EditingContext context) 
            {
                this.instance = instance; 
                this.context = context;
            }

            public object Instance 
            {
                get { return this.instance; } 
            } 

            public EditingContext Context 
            {
                get { return this.context; }
            }
        } 
        internal event EventHandler PreviewLoad;
 
        [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.InitializeReferenceTypeStaticFieldsInline, 
            Justification = "The static constructor is required to initialize the PropertyInspector metadata.")]
        static WorkflowDesigner() 
        {
            InitializePropertyInspectorMetadata();
            DesignerMetadata metaData = new DesignerMetadata();
            metaData.Register(); 
        }
 
        public WorkflowDesigner() 
        {
            // create our perf trace provider first 
            this.perfEventProvider = new DesignerPerfEventProvider();

            this.context = new EditingContext();
            this.context.Items.SetValue(new ReadOnlyState { IsReadOnly = false }); 
            this.view = new Grid();
            this.view.Focusable = false; 
            this.propertyInspector = new PropertyInspector(); 
            this.propertyInspector.DesignerContextItemManager = this.context.Items;
            PropertyInspectorMergedResources.PropertyInspectorResources = this.propertyInspector.Resources; 
            WorkflowDesignerColors.FontResources = this.propertyInspector.Resources;
            //add the resource dictionary to application resource so every component could reference it
            if (Application.Current == null)
            { 
                //create an applicatio if it doesn't exist, make sure it will not shutdown after windows being shut down
                Application app = new Application(); 
                app.ShutdownMode = ShutdownMode.OnExplicitShutdown; 
            }
            Fx.Assert(Application.Current != null, "Application and resources must be there"); 
            Application.Current.Resources.MergedDictionaries.Add(this.propertyInspector.Resources);

            AttachedPropertiesService propertiesService = new AttachedPropertiesService();
            this.context.Services.Publish(typeof(AttachedPropertiesService), propertiesService); 

            undoEngine = new UndoEngine(context); 
            this.context.Services.Publish(typeof(UndoEngine), undoEngine); 
            undoEngine.ExecuteUndo += new EventHandler(OnExecuteUndo);
 
            this.context.Services.Publish(this.ValidationService);
            this.context.Services.Publish(this.perfEventProvider);
            this.context.Services.Publish(new FeatureManager(this.context));
 
            InitializePropertyInspectorResources();
            InitializePropertyInspectorCommandHandling(); 
 
            this.Context.Items.Subscribe(delegate(ErrorItem errorItem)
            { 
                ErrorView errorView = new ErrorView();
                errorView.Message = errorItem.Message;
                errorView.Details = errorItem.Details;
                this.view.Children.Clear(); 
                this.view.Children.Add(errorView);
            } 
                ); 

            this.context.Items.Subscribe(new SubscribeContextCallback(OnReadonlyStateChanged)); 

            this.context.Services.Subscribe(s => this.xamlLoadErrorService = s);

            this.PreviewLoad += VisualBasicSettingsHandler.PreviewLoadRoot; 
            this.view.Loaded += (s, e) =>
            { 
                //when view is loaded, check if user did provide his own WindowHelperService - if not, provide a default one 
                if (!this.context.Services.Contains())
                { 
                    IntPtr hWND = IntPtr.Zero;
                    Window ownerWindow = Window.GetWindow(this.view);
                    if (null != ownerWindow)
                    { 
                        WindowInteropHelper helper = new WindowInteropHelper(ownerWindow);
                        hWND = helper.Handle; 
                    } 
                    this.Context.Services.Publish(new WindowHelperService(hWND));
                } 
                WindowHelperService whs = this.context.Services.GetService();
                whs.View = this.view;

                //check if workflow command extension item is available - if not, provide default one 
                if (!this.context.Items.Contains())
                { 
                    WorkflowCommandExtensionItem item = new WorkflowCommandExtensionItem(new DefaultCommandExtensionCallback()); 
                    this.context.Items.SetValue(item);
                } 

                ComponentDispatcher.EnterThreadModal += new EventHandler(ComponentDispatcher_EnterThreadModal);
                ComponentDispatcher.LeaveThreadModal += new EventHandler(ComponentDispatcher_LeaveThreadModal);
            }; 

            this.view.Unloaded += (s, e) => 
            { 
                ComponentDispatcher.EnterThreadModal -= new EventHandler(ComponentDispatcher_EnterThreadModal);
                ComponentDispatcher.LeaveThreadModal -= new EventHandler(ComponentDispatcher_LeaveThreadModal); 
            };

            this.view.IsKeyboardFocusWithinChanged += (s, e) =>
            { 
                // The ModelTreeManager is null when there is an active ErrorItem.
                // We have nothing to write to text in this case. 
                if (this.modelTreeManager != null && (bool)e.NewValue == false) 
                {
                    if ((FocusManager.GetFocusedElement(this.view) as TextBox) != null) 
                    {
                        FocusManager.SetFocusedElement(this.view, null);
                        this.NotifyModelChanged();
                    } 
                }
            }; 
        } 

        void ComponentDispatcher_EnterThreadModal(object sender, EventArgs e) 
        {
            IModalService modalService = Context.Services.GetService();
            if (modalService != null)
            { 
                modalService.SetModalState(true);
            } 
        } 

        void ComponentDispatcher_LeaveThreadModal(object sender, EventArgs e) 
        {
            IModalService modalService = Context.Services.GetService();
            if (modalService != null)
            { 
                modalService.SetModalState(false);
            } 
        } 

        WorkflowDesignerXamlSchemaContext XamlSchemaContext 
        {
            get
            {
                if (this.workflowDesignerXamlSchemaContext == null) 
                {
                    this.workflowDesignerXamlSchemaContext = new WorkflowDesignerXamlSchemaContext(GetLocalAssemblyName(), this.Context); 
 
                }
 
                return this.workflowDesignerXamlSchemaContext;
            }
        }
 
        string GetLocalAssemblyName()
        { 
            AssemblyContextControlItem assemblyItem = this.Context.Items.GetValue(); 
            return assemblyItem != null && assemblyItem.LocalAssemblyName != null ? assemblyItem.LocalAssemblyName.Name : null;
        } 

        void OnExecuteUndo(object sender, UndoUnitEventArgs e)
        {
            // If an action had caused the errorview to be shown, and undo was executed after that 
            // try to put back the viewmanagerview back as the rootview of the designer.
            // may be the undo might help recover from the problem. 
            if (!this.view.Children.Contains((UIElement)this.viewManager.View)) 
            {
                this.view.Children.Clear(); 
                this.view.Children.Add((UIElement)this.viewManager.View);

                // Clear out the error condition
                ErrorItem errorItem = this.context.Items.GetValue(); 
                errorItem.Message = null;
                errorItem.Details = null; 
            } 
        }
 
        internal ValidationService ValidationService
        {
            get
            { 
                if (this.validationService == null)
                { 
                    this.validationService = new ValidationService(this.context); 
                    this.validationService.ErrorsMarked += ArgumentFixer.UpdateInvalidArgumentsIfNecessary;
                } 

                return this.validationService;
            }
        } 

        public UIElement View 
        { 
            get
            { 
                return this.view;
            }
        }
 
        public UIElement PropertyInspectorView
        { 
            get 
            {
                return this.propertyInspector; 
            }
        }
        public EditingContext Context
        { 
            get
            { 
                return this.context; 
            }
        } 

        public ContextMenu ContextMenu
        {
            get 
            {
                if (null != this.context) 
                { 
                    DesignerView designerView = this.context.Services.GetService();
                    if (null != designerView) 
                    {
                        return designerView.ContextMenu;
                    }
                } 
                return null;
            } 
        } 

        public string Text 
        {
            get { return this.text; }
            set { this.text = value; }
        } 

        [SuppressMessage(FxCop.Category.Design, "CA1044:PropertiesShouldNotBeWriteOnly", 
            Justification = "The host just sets this property for the designer to know which colors to display.")] 
        public string PropertyInspectorFontAndColorData
        { 
            set
            {
                StringReader stringReader = new StringReader(value);
                XmlReader xmlReader = XmlReader.Create(stringReader); 
                Hashtable fontAndColorDictionary = (Hashtable)System.Windows.Markup.XamlReader.Load(xmlReader);
                foreach (string key in fontAndColorDictionary.Keys) 
                { 
                    if (this.propertyInspector.Resources.Contains(key))
                    { 
                        this.propertyInspector.Resources[key] = fontAndColorDictionary[key];
                    }
                    else
                    { 
                        this.propertyInspector.Resources.Add(key, fontAndColorDictionary[key]);
                    } 
                    WorkflowDesignerColors.ColorServiceColors[key] = fontAndColorDictionary[key]; 
                }
                Application.Current.Resources.MergedDictionaries.Add(this.propertyInspector.Resources); 
            }
        }

        public IDesignerDebugView DebugManagerView 
        {
            get 
            { 
                return this.DebuggerService;
            } 
        }

        DebuggerService DebuggerService
        { 
            get
            { 
                if (this.debuggerService == null) 
                {
                    this.debuggerService = new DebuggerService(this.context); 
                    this.context.Services.Publish(this.debuggerService);
                }
                return this.debuggerService;
            } 

        } 
 

        public bool IsInErrorState() 
        {
            ErrorItem errorItem = this.context.Items.GetValue();
            return errorItem.Message != null && errorItem.Details != null ? true : false;
        } 

        // Load using Xaml. 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes, 
            Justification = "Deserializer might throw if it fails to deserialize. Catching all exceptions to avoid VS Crash.")]
        [SuppressMessage("Reliability", "Reliability108", 
            Justification = "Deserializer might throw if it fails to deserialize. Catching all exceptions to avoid VS crash.")]
        public void Load()
        {
            this.perfEventProvider.WorkflowDesignerLoadStart(); 
            if (!string.IsNullOrEmpty(this.text))
            { 
                try 
                {
                    this.perfEventProvider.WorkflowDesignerDeserializeStart(); 

                    IList loadErrors;
                    object deserializedObject = DeserializeString(this.text, out loadErrors);
 
                    this.perfEventProvider.WorkflowDesignerDeserializeEnd();
 
                    if (deserializedObject != null) 
                    {
                        this.Load(deserializedObject); 
                        this.ValidationService.ValidateWorkflow(ValidationReason.Load);
                    }
                    else
                    { 
                        StringBuilder details = new StringBuilder();
                        foreach (XamlLoadErrorInfo error in loadErrors) 
                        { 
                            details.AppendLine(error.Message);
                        } 
                        this.Context.Items.SetValue(new ErrorItem() { Message = SR.SeeErrorWindow, Details = details.ToString() });
                    }
                    if (loadErrors != null)
                    { 
                        RaiseLoadErrors(loadErrors);
                    } 
                    this.isModelChanged = false; 
                }
                catch (Exception e) 
                {
                    this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() });
                    RaiseLoadError(e);
                } 
            }
            else 
            { 
                this.Context.Items.SetValue(new ErrorItem() { Message = string.Empty, Details = string.Empty });
            } 
            this.perfEventProvider.WorkflowDesignerLoadComplete();
        }

        public void Load(string fileName) 
        {
            IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService(); 
            if (documentPersistenceService != null) 
            {
                this.Load(documentPersistenceService.Load(fileName)); 
            }
            else
            {
                using (StreamReader fileStream = new StreamReader(fileName)) 
                {
                    this.loadedFile = fileName; 
                    WorkflowFileItem fileItem = new WorkflowFileItem(); 
                    fileItem.LoadedFile = fileName;
                    this.context.Items.SetValue(fileItem); 
                    this.Text = fileStream.ReadToEnd();
                    this.Load();
                }
            } 
            if (this.debuggerService != null && !this.IsInErrorState())
            { 
                this.UpdateSourceLocationMappingInDebuggerService(); 
            }
        } 


        // This supports  loading objects instead of xaml into the designer
        public void Load(object instance) 
        {
            if (isLoaded) 
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowDesignerLoadShouldBeCalledOnlyOnce));
            } 

            isLoaded = true;

            if (instance == null) 
            {
                throw FxTrace.Exception.AsError(new ArgumentNullException("instance")); 
            } 

            if (this.PreviewLoad != null) 
            {
                this.PreviewLoad(this, new PreviewLoadEventArgs(instance, this.context));
            }
 
            modelTreeManager = new ModelTreeManager(this.context);
            modelTreeManager.Load(instance); 
            this.context.Services.Publish(typeof(ModelTreeManager), modelTreeManager); 

            viewManager = GetViewManager(this.modelTreeManager.Root); 
            view.Children.Add((UIElement)viewManager.View);
            modelTreeManager.EditingScopeCompleted += new EventHandler(OnEditingScopeCompleted);

 

            this.view.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, 
                             new Action(() => { this.perfEventProvider.WorkflowDesignerApplicationIdleAfterLoad(); })); 

            //Subscribe to the ViewStateChanged event of ViewStateService to show document dirty. It would be published in the call to GetViewManager(). 
            WorkflowViewStateService wfViewStateService = this.Context.Services.GetService(typeof(ViewStateService)) as WorkflowViewStateService;
            if (wfViewStateService != null)
            {
                wfViewStateService.UndoableViewStateChanged += new ViewStateChangedEventHandler(OnViewStateChanged); 
            }
            this.isModelChanged = false; 
        } 

 
        void OnViewStateChanged(object sender, ViewStateChangedEventArgs e)
        {
            NotifyModelChanged();
        } 

        void OnEditingScopeCompleted(object sender, EditingScopeEventArgs e) 
        { 
            if (e.EditingScope.HasEffectiveChanges)
            { 
                NotifyModelChanged();
                if (!this.modelTreeManager.RedoUndoInProgress
                    && undoEngine != null
                    && !e.EditingScope.SuppressUndo) 
                {
                    undoEngine.AddUndoUnit(new EditingScopeUndoUnit(this, this.modelTreeManager, e.EditingScope)); 
                } 
                if (e.EditingScope.HasModelChanges)
                { 
                    this.ValidationService.ValidateWorkflow(ValidationReason.ModelChange);
                }
            }
        } 

        public void Save(string fileName) 
        { 
            this.isModelChanged = true; // ensure flushing any viewstate changes that does not imply model changed.
            Flush(); 
            using (StreamWriter fileStreamWriter = new StreamWriter(fileName, false, Encoding.UTF8))
            {
                fileStreamWriter.Write(this.Text);
                fileStreamWriter.Flush(); 
            }
 
            this.ValidationService.ValidateWorkflow(ValidationReason.Save); 

            if (this.debuggerService != null) 
            {
                try
                {
                    this.CollectSourceLocationMapping(); 
                }
                catch (Exception ex) 
                { 
                    System.Diagnostics.Trace.WriteLine("Save operation completed, however problem encountered during reading it back.\nError: " + ex.Message);
                    throw; 
                }
            }

        } 

        public void Flush() 
        { 
            if (this.modelTreeManager == null)
            { 
                // It's possible for modelTreeManager to be null if Load is called but the xaml file being loaded is invalid.
                // We only want to throw exception if Load hasn't been called yet.
                if (IsInErrorState() == false)
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowDesignerLoadShouldBeCalledFirst));
                } 
            } 
            else
            { 
                this.FlushEdits();
                IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService();
                if (documentPersistenceService != null)
                { 
                    documentPersistenceService.Flush(this.modelTreeManager.Root.GetCurrentValue());
                } 
                else 
                {
                    this.WriteModelToText(); 
                }
            }
        }
 
        void FlushEdits()
        { 
            UIElement oldFocus = null; 
            //check if property grid has keyboard focus within, if yes - get focused control
            if (null != this.propertyInspector && this.propertyInspector.IsKeyboardFocusWithin) 
            {
                oldFocus = FocusManager.GetFocusedElement(this.propertyInspector) as UIElement;
            }
            //check if view has keyboard focus within, if yes - get focused control 
            if (null != this.view && this.view.IsKeyboardFocusWithin)
            { 
                oldFocus = FocusManager.GetFocusedElement(this.view) as UIElement; 
            }
            if (null != oldFocus) 
            {
                RoutedCommand cmd = DesignerView.CommitCommand as RoutedCommand;
                if (cmd != null)
                { 
                    cmd.Execute(null, oldFocus);
                } 
            } 

            //commit changes within arguments and variables editor 
            var designerView = this.Context.Services.GetService();
            if (null != designerView)
            {
                if (null != designerView.arguments1) 
                {
                    DataGridHelper.CommitPendingEdits(designerView.arguments1.argumentsDataGrid); 
                } 
                if (null != designerView.variables1)
                { 
                    DataGridHelper.CommitPendingEdits(designerView.variables1.variableDataGrid);
                }
            }
        } 

        void InitializePropertyInspectorCommandHandling() 
        { 
        }
 
        void InitializePropertyInspectorResources()
        {
            this.propertyInspector.Resources.MergedDictionaries.Add(PropertyInspectorResources.GetResources());
        } 

        static void InitializePropertyInspectorMetadata() 
        { 
            PropertyInspectorMetadata.Initialize();
        } 

        ViewManager GetViewManager(ModelItem modelItem)
        {
            Fx.Assert(modelItem != null, "modelItem cannot be null"); 
            ViewManager viewManager = null;
            // First we look for a ViewManagerAttribute. for example a ServiceContractRoot tag, could use 
            // use its own view manager if it wanted to . 
            ViewManagerAttribute viewManagerAttribute = TypeDescriptor.GetAttributes(modelItem.ItemType)[typeof(ViewManagerAttribute)] as ViewManagerAttribute;
            if (viewManagerAttribute != null && viewManagerAttribute.ViewManagerType != null) 
            {
                viewManager = (ViewManager)Activator.CreateInstance(viewManagerAttribute.ViewManagerType);

            } 
            // If no viewmanager attribute is found we default to the workflowviewmanager
            if (viewManager == null) 
            { 
                viewManager = new WorkflowViewManager();
            } 
            viewManager.Initialize(this.context);
            return viewManager;
        }
 
        void NotifyModelChanged()   // Notify text is going to changed
        { 
            IDocumentPersistenceService documentPersistenceService = this.Context.Services.GetService(); 
            if (documentPersistenceService != null)
            { 
                documentPersistenceService.OnModelChanged(this.modelTreeManager.Root.GetCurrentValue());
            }
            else
            { 
                this.isModelChanged = true;
                if (this.ModelChanged != null) 
                { 
                    this.ModelChanged.Invoke(this, null);
                } 
            }
        }

 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes,
            Justification = "Serializer might throw if it fails to serialize. Catching all exceptions to avoid VS Crash.")] 
        [SuppressMessage("Reliability", "Reliability108", 
            Justification = "Serializer might throw if it fails to serialize. Catching all exceptions to avoid VS crash.")]
        void WriteModelToText() 
        {
            this.perfEventProvider.WorkflowDesignerSerializeStart();
            object rootModelObject = this.modelTreeManager.Root.GetCurrentValue();
            // if we are serializing a activity schema type, remove the namespace in the Name property. 
            ActivityBuilder activityBuilderType = rootModelObject as ActivityBuilder;
 
            // now try to serialize 
            try
            { 
                string newText = SerializeToString(rootModelObject);
                if (string.IsNullOrEmpty(this.Text) ||
                    (this.isModelChanged && !string.Equals(newText, this.Text, StringComparison.Ordinal)))
                { 
                    this.Text = newText;
                    if (this.TextChanged != null) 
                    { 
                        this.TextChanged.Invoke(this, null);
                    } 
                }
                this.isModelChanged = false;
            }
            catch (Exception e) 
            {
                this.Context.Items.SetValue(new ErrorItem() { Message = e.Message, Details = e.ToString() }); 
            } 
            this.perfEventProvider.WorkflowDesignerSerializeEnd();
        } 

        internal object DeserializeString(string text)
        {
            IList loadErrors; 
            return DeserializeString(text, out loadErrors);
        } 
 
        internal object DeserializeString(string text, out IList loadErrors)
        { 
            try
            {
                return DeserializeString(text, false, out loadErrors);
            } 
            catch (XamlObjectWriterException)
            { 
                // Fall back to error-tolerant path. We don't do this by default for perf reasons. 
                return DeserializeString(text, true, out loadErrors);
            } 
        }

        internal object DeserializeString(string text, bool errorTolerant, out IList loadErrors)
        { 
            using (XamlXmlReader xamlXmlReader =
                new XamlXmlReader(XmlReader.Create(new StringReader(text)), 
                        this.XamlSchemaContext, 
                        new XamlXmlReaderSettings { ProvideLineInfo = true }))
            { 
                using (XamlDebuggerXmlReader debuggerReader = new XamlDebuggerXmlReader(xamlXmlReader, new StringReader(text)))
                {
                    using (System.Xaml.XamlReader activityBuilderReader = ActivityXamlServices.CreateBuilderReader(debuggerReader))
                    { 
                        if (errorTolerant)
                        { 
                            ErrorTolerantObjectWriter tolerantWriter = new ErrorTolerantObjectWriter(activityBuilderReader.SchemaContext); 
                            tolerantWriter.LocalAssemblyName = GetLocalAssemblyName();
                            XamlServices.Transform(activityBuilderReader, tolerantWriter); 
                            loadErrors = tolerantWriter.LoadErrors;
                            object result = tolerantWriter.Result;
                            ErrorActivity.SetHasErrorActivities(result, true);
                            return result; 
                        }
                        else 
                        { 
                            loadErrors = null;
                            XamlObjectWriter objectWriter = new XamlObjectWriter(activityBuilderReader.SchemaContext); 
                            if (this.XamlSchemaContext.HasLocalAssembly)
                            {
                                CopyNamespacesAndAddLocalAssembly(activityBuilderReader, objectWriter);
                            } 
                            XamlServices.Transform(activityBuilderReader, objectWriter);
                            return objectWriter.Result; 
                        } 
                    }
                } 
            }
        }

        internal string SerializeToString(object obj) 
        {
            TextWriter textWriter = new StringWriter(CultureInfo.InvariantCulture); 
 
            WorkflowDesignerXamlSchemaContext schemaContext = obj is ActivityBuilder ? this.XamlSchemaContext : new WorkflowDesignerXamlSchemaContext(null);
 
            using (textWriter)
            {
                using (System.Xaml.XamlWriter writer =
                    ActivityXamlServices.CreateBuilderWriter(new DesignTimeXamlWriter(textWriter, 
                            schemaContext)))
                { 
                    XamlObjectReader objectReader = new XamlObjectReader(obj, schemaContext); 
                    if (ErrorActivity.GetHasErrorActivities(obj))
                    { 
                        ErrorTolerantObjectWriter.TransformAndStripErrors(objectReader, writer);
                    }
                    else
                    { 
                        XamlServices.Transform(objectReader, writer);
 
                    } 
                }
            } 
            return textWriter.ToString();
        }

        // Copy the root namespaces from a reader to a writer. 
        // DesignTimeXamlWriter follows proper XAML convention by omitting the assembly name from
        // clr-namespaces in the local assembly. However, VB Expressions aren't local-assembly-aware, 
        // and require an assembly name. So for every clr-namespace with no assembly name, we add an 
        // additional namespace record with an assembly name, to support VB.
        // We only do this at the root level, since the designer only writes out namespaces at the root level. 
        void CopyNamespacesAndAddLocalAssembly(System.Xaml.XamlReader activityBuilderReader, System.Xaml.XamlWriter objectWriter)
        {
            // Designer loads alwas provide line info
            IXamlLineInfo lineInfo = (IXamlLineInfo)activityBuilderReader; 
            IXamlLineInfoConsumer lineInfoConsumer = (IXamlLineInfoConsumer)objectWriter;
            HashSet definedPrefixes = new HashSet(); 
            List localAsmNamespaces = null; 

            while (activityBuilderReader.Read()) 
            {
                lineInfoConsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
                if (activityBuilderReader.NodeType == XamlNodeType.NamespaceDeclaration)
                { 
                    definedPrefixes.Add(activityBuilderReader.Namespace.Prefix);
                    if (this.XamlSchemaContext.IsClrNamespaceWithNoAssembly(activityBuilderReader.Namespace.Namespace)) 
                    { 
                        if (localAsmNamespaces == null)
                        { 
                            localAsmNamespaces = new List();
                        }
                        localAsmNamespaces.Add(activityBuilderReader.Namespace);
                    } 
                    objectWriter.WriteNode(activityBuilderReader);
                } 
                else 
                {
                    if (localAsmNamespaces != null) 
                    {
                        foreach (NamespaceDeclaration ns in localAsmNamespaces)
                        {
                            string prefix = null; 
                            int i = 0;
                            do 
                            { 
                                i++;
                                prefix = ns.Prefix + i.ToString(CultureInfo.InvariantCulture); 
                            }
                            while (definedPrefixes.Contains(prefix));
                            string fullNs = this.XamlSchemaContext.AddLocalAssembly(ns.Namespace);
                            objectWriter.WriteNamespace(new NamespaceDeclaration(fullNs, prefix)); 
                            definedPrefixes.Add(prefix);
                        } 
                    } 
                    objectWriter.WriteNode(activityBuilderReader);
                    return; 
                }
            }
        }
 
        void OnReadonlyStateChanged(ReadOnlyState state)
        { 
            if (null != this.propertyInspector) 
            {
                this.propertyInspector.IsReadOnly = state.IsReadOnly; 
            }
        }

        void UpdateSourceLocationMappingInDebuggerService() 
        {
            object rootInstance = this.GetRootInstance(); 
            Dictionary sourceLocationMapping = new Dictionary(); 

            if (rootInstance != null) 
            {
                Activity documentRootElement = GetRootWorkflowElement(rootInstance);
                if (documentRootElement != null)
                { 
                    this.CollectMappingFromSourceLocationProvider(documentRootElement, documentRootElement, sourceLocationMapping,
                        this.Context.Items.GetValue().LoadedFile); 
                } 
            }
 
            // Notify the DebuggerService of the new sourceLocationMapping.
            // When rootInstance == null, it'll just reset the mapping.
            if (this.debuggerService != null)
            { 
                this.debuggerService.UpdateSourceLocations(sourceLocationMapping);
            } 
        } 

        void CollectSourceLocationMapping() 
        {
            //Regenerate new SourceLocation mapping.
            object deserializedObject = this.DeserializeString(this.Text);
            if (deserializedObject != null) 
            {
                Activity documentRootElement = GetRootWorkflowElement(this.GetRootInstance()); 
                Activity deserializedRootElement = GetRootWorkflowElement(deserializedObject); 

                Dictionary sourceLocationMapping = new Dictionary(); 
                if (documentRootElement != null && deserializedRootElement != null)
                {
                    string loadedFile = this.Context.Items.GetValue().LoadedFile;
                    this.CollectMappingFromSourceLocationProvider(documentRootElement, deserializedRootElement, sourceLocationMapping, loadedFile); 
                }
 
                //Notify the DebuggerService of the Save so that it can recompute its cache. 
                DebuggerService debuggerService = this.DebugManagerView as DebuggerService;
                if (debuggerService != null) 
                {
                    debuggerService.UpdateSourceLocations(sourceLocationMapping);
                }
            } 
            else
            { 
                Fx.Assert("Unable to deserialize Xaml representation."); 
            }
        } 

        void CollectMappingFromSourceLocationProvider(Activity documentRootElement, Activity deserializedRootElement, Dictionary sourceLocationMapping, string loadedFile)
        {
            try 
            {
                SourceLocationProvider.CollectMapping(documentRootElement, deserializedRootElement, sourceLocationMapping, loadedFile); 
            } 
            catch (System.Exception ex)
            { 
                System.Diagnostics.Debug.WriteLine("Exception caught, debugger functionalities may be limited: " + ex.Message);
                if (Fx.IsFatal(ex))
                {
                    throw; 
                }
            } 
        } 

        // Get root Activity.  Currently only handle when the object is ActivityBuilder or Activity. 
        // May return null if it does not know how to get the root activity.
        static Activity GetRootWorkflowElement(object rootModelObject)
        {
            Fx.Assert(rootModelObject != null, "Cannot pass null as rootModelObject"); 

            Activity rootWorkflowElement; 
            IDebuggableWorkflowTree debuggableWorkflowTree = rootModelObject as IDebuggableWorkflowTree; 
            if (debuggableWorkflowTree != null)
            { 
                rootWorkflowElement = debuggableWorkflowTree.GetWorkflowRoot();
            }
            else // Loose xaml case.
            { 
                rootWorkflowElement = rootModelObject as Activity;
            } 
            return rootWorkflowElement; 
        }
 
        object GetRootInstance()
        {
            return this.modelTreeManager.Root.GetCurrentValue();
        } 

        void RaiseLoadError(Exception e) 
        { 
            if (this.xamlLoadErrorService != null)
            { 
                XamlLoadErrorInfo errorInfo = null;
                XamlException xamlEx = e as XamlException;
                if (xamlEx != null)
                { 
                    errorInfo = new XamlLoadErrorInfo(xamlEx.Message, xamlEx.LineNumber, xamlEx.LinePosition);
                } 
                else 
                {
                    XmlException xmlEx = e as XmlException; 
                    if (xmlEx != null)
                    {
                        errorInfo = new XamlLoadErrorInfo(xmlEx.Message, xmlEx.LineNumber, xmlEx.LinePosition);
                    } 
                }
                if (errorInfo != null) 
                { 
                    var errors = new XamlLoadErrorInfo[] { errorInfo };
                    xamlLoadErrorService.ShowXamlLoadErrors(errors); 
                }
            }
        }
 
        void RaiseLoadErrors(IList loadErrors)
        { 
            if (this.xamlLoadErrorService != null) 
            {
                this.xamlLoadErrorService.ShowXamlLoadErrors(loadErrors); 
            }
        }

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK