//----------------------------------------------------------------
// 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