Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / View / ExpressionTextBox.xaml.cs / 1590394 / ExpressionTextBox.xaml.cs

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

namespace System.Activities.Presentation.View 
{
    using System.Activities.Presentation.Internal.PropertyEditing; 
    using System.Activities.Presentation.Model; 
    using System.Activities.Presentation.Services;
    using System.Activities.Presentation.Validation; 
    using System.Activities.Presentation.Hosting;
    using System.Activities.Presentation.Xaml;
    using System.Activities.ExpressionParser;
    using System.Activities.Expressions; 
    using System.Activities.XamlIntegration;
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Linq;
    using System.Runtime;
    using System.Windows; 
    using System.Windows.Automation;
    using System.Windows.Automation.Peers; 
    using System.Windows.Controls; 
    using System.Windows.Data;
    using System.Windows.Input; 
    using System.Windows.Media;
    using Microsoft.VisualBasic.Activities;
    using System.Windows.Threading;
    using System.Threading; 

    //This control is used for expression editing in activity designers. 
    //It uses the Activity TypeConverter to convert between a Activity and its string representation. 
    //It defines 3 dependency properties - OwnerActivity, ExpressionModelItem and ExpressionType.
    //ActivityModelItem is used to create the parser context required by the TypeConverter. 
    //ExpressionType is the type of the expression associated with this text box. This is required by the TypeConverter.

    public sealed partial class ExpressionTextBox : ContentControl
    { 
        internal static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnTextChanged), new CoerceValueCallback(OnTextCoerceValue))); 
 
        public static readonly DependencyProperty HintTextProperty = DependencyProperty.Register("HintText", typeof(string), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(SR.ExpressionDefaultText, new PropertyChangedCallback(OnHintTextChanged))); 

        internal static readonly DependencyProperty ValidationStateProperty = DependencyProperty.Register("ValidationState", typeof(ValidationState), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(ValidationState.Valid));
 
        public static readonly DependencyProperty ExpressionProperty = DependencyProperty.Register("Expression", typeof(ModelItem), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnExpressionChanged))); 
 
        public static readonly DependencyProperty ExpressionTypeProperty = DependencyProperty.Register("ExpressionType", typeof(Type), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnExpressionTypeChanged))); 

        public static readonly DependencyProperty OwnerActivityProperty = DependencyProperty.Register("OwnerActivity", typeof(ModelItem), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnOwnerModelItemChanged)));
 
        public static readonly DependencyProperty UseLocationExpressionProperty = DependencyProperty.Register("UseLocationExpression", typeof(bool), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(false, OnUseLocationExpressionChanged)); 
 
        public static readonly DependencyProperty PathToArgumentProperty = DependencyProperty.Register("PathToArgument", typeof(string), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(null, OnPathToArgumentChanged)); 

        public static readonly DependencyProperty IsSupportedExpressionProperty = DependencyProperty.Register("IsSupportedExpression", typeof(bool), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(true));
 
        public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = DependencyProperty.Register("VerticalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(ExpressionTextBox),
                new PropertyMetadata(ScrollBarVisibility.Hidden)); 
 
        public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = DependencyProperty.Register("HorizontalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(ExpressionTextBox),
                new PropertyMetadata(ScrollBarVisibility.Hidden)); 

        public static readonly DependencyProperty MaxLinesProperty = DependencyProperty.Register("MaxLines", typeof(int), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(Int32.MaxValue, new PropertyChangedCallback(OnLinesChanged)));
 
        public static readonly DependencyProperty MinLinesProperty = DependencyProperty.Register("MinLines", typeof(int), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(1, new PropertyChangedCallback(OnLinesChanged))); 
 
        public static readonly DependencyProperty ExplicitCommitProperty = DependencyProperty.Register("ExplicitCommit", typeof(bool), typeof(ExpressionTextBox),
                new FrameworkPropertyMetadata(false)); 

        public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register("DefaultValue", typeof(string), typeof(ExpressionTextBox),
                new PropertyMetadata(null));
 
        public static readonly DependencyProperty AcceptsReturnProperty = DependencyProperty.Register("AcceptsReturn", typeof(bool), typeof(ExpressionTextBox),
                new PropertyMetadata(true, OnAcceptsReturnChanged)); 
 
        public static readonly DependencyProperty AcceptsTabProperty = DependencyProperty.Register("AcceptsTab", typeof(bool), typeof(ExpressionTextBox),
                new PropertyMetadata(false, OnAcceptsTabChanged)); 

        public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(ExpressionTextBox),
                new PropertyMetadata(false));
 
        internal static readonly DependencyProperty EditingStateProperty = DependencyProperty.Register("EditingState", typeof(EditingState), typeof(ExpressionTextBox),
                new PropertyMetadata(EditingState.Idle)); 
 
        internal static readonly DependencyProperty HasValidationErrorProperty = DependencyProperty.Register("HasValidationError", typeof(bool), typeof(ExpressionTextBox),
                new PropertyMetadata(false)); 

        internal static readonly DependencyProperty ValidationErrorMessageProperty = DependencyProperty.Register("ValidationErrorMessage", typeof(string), typeof(ExpressionTextBox),
                new PropertyMetadata(null));
 
        internal static readonly DependencyProperty ExpressionTextProperty = DependencyProperty.Register("ExpressionText", typeof(string), typeof(ExpressionTextBox),
                new PropertyMetadata(null)); 
 
        internal static readonly DependencyProperty IsIndependentExpressionProperty = DependencyProperty.Register("IsIndependentExpression", typeof(bool), typeof(ExpressionTextBox),
                new PropertyMetadata(new PropertyChangedCallback(OnIsIndependentExpressionChanged))); 

        public static readonly RoutedEvent EditorLostLogicalFocusEvent =
            EventManager.RegisterRoutedEvent("EditorLostLogicalFocus", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExpressionTextBox));
 
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
        public static readonly ICommand CompleteWordCommand = new RoutedCommand("CompleteWordCommand", typeof(ExpressionTextBox)); 
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] 
        public static readonly ICommand GlobalIntellisenseCommand = new RoutedCommand("GlobalIntellisenseCommand", typeof(ExpressionTextBox));
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] 
        public static readonly ICommand ParameterInfoCommand = new RoutedCommand("ParameterInfoCommand", typeof(ExpressionTextBox));
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
        public static readonly ICommand QuickInfoCommand = new RoutedCommand("QuickInfoCommand", typeof(ExpressionTextBox));
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] 
        public static readonly ICommand IncreaseFilterLevelCommand = new RoutedCommand("IncreaseFilterLevelCommand", typeof(ExpressionTextBox));
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] 
        public static readonly ICommand DecreaseFilterLevelCommand = new RoutedCommand("DecreaseFilterLevelCommand", typeof(ExpressionTextBox)); 

        bool internalModelItemChange = false; 
        string previousText = null;
        EditingContext context;
        ModelProperty expressionModelProperty;
        TypeConverter expressionConverter; 
        bool initialized = false;
 
        IExpressionEditorService expressionEditorService; 
        IExpressionEditorInstance expressionEditorInstance;
 
        Control hostControl;
        string editorName;
        double blockHeight = double.NaN;
        double blockWidth = double.NaN; 
        bool isExpressionLoaded = false;
        bool isBeginEditPending = false; 
 
        DesignerPerfEventProvider perfProvider;
        ModelItem boundedExpression = null; 
        BackgroundWorker validator = null;
        const int ValidationWaitTime = 800;

        PropertyChangedEventHandler onExpressionModelItemChangedHandler; 

        public ExpressionTextBox() 
        { 
            InitializeComponent();
 
            this.MinHeight = this.FontSize + 4; /* 4 pixels for border*/

            this.context = null;
            this.editorName = null; 

            this.ContentTemplate = (DataTemplate)FindResource("textblock"); 
            this.Loaded += this.OnExpressionTextBoxLoaded; 
            this.Unloaded += this.OnExpressionTextBoxUnloaded;
 
            CommandBinding CommitBinding = new CommandBinding(DesignerView.CommitCommand, OnCommitCommandExecute, OnCommitCommandCanExecute);
            this.CommandBindings.Add(CommitBinding);
        }
 
        public event RoutedEventHandler EditorLostLogicalFocus
        { 
            add 
            {
                this.AddHandler(ExpressionTextBox.EditorLostLogicalFocusEvent, value); 
            }
            remove
            {
                this.RemoveHandler(ExpressionTextBox.EditorLostLogicalFocusEvent, value); 
            }
        } 
 
        PropertyChangedEventHandler OnExpressionModelItemChanged
        { 
            get
            {
                if (this.onExpressionModelItemChangedHandler == null)
                { 
                    this.onExpressionModelItemChangedHandler = new PropertyChangedEventHandler(this.expressionModelItem_PropertyChanged);
                } 
 
                return this.onExpressionModelItemChangedHandler;
            } 
        }

        protected override void OnContextMenuOpening(ContextMenuEventArgs e)
        { 
            e.Handled = true;
        } 
 
        protected override void OnPreviewMouseRightButtonDown(MouseButtonEventArgs e)
        { 
            base.OnPreviewMouseRightButtonDown(e);
            e.Handled = true;
        }
 
        static object OnTextCoerceValue(DependencyObject dp, object value)
        { 
            string tempText = value as string; 
            ExpressionTextBox etb = dp as ExpressionTextBox;
            if (etb != null) 
            {
                if (tempText != null)
                {
                    tempText = tempText.Trim(); 
                }
            } 
            return tempText; 
        }
 
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new ExpressionTextBoxAutomationPeer(this);
        } 

        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) 
        { 
            base.OnLostKeyboardFocus(e);
 
            if (this.expressionEditorInstance != null &&
            (this.expressionEditorInstance.HasAggregateFocus ||
             (this.hostControl != null && this.hostControl.IsFocused)))
            { 
                return;
            } 
 
            DoLostFocus();
        } 

        private void DoLostFocus()
        {
            KillValidator(); 

            ValidateExpression(this); 
 
            if (this.Context != null)
            {   // Unselect if this is the currently selected one. 
                ExpressionSelection current = this.Context.Items.GetValue();
                if (current != null && current.ModelItem == this.Expression)
                {
                    ExpressionSelection emptySelection = new ExpressionSelection(null); 
                    this.Context.Items.SetValue(emptySelection);
                } 
            } 

            // Generate and validate the expression. 
            // Get the text from the snapshot and set it to the Text property
            if (this.expressionEditorInstance != null)
            {
                this.expressionEditorInstance.ClearSelection(); 
            }
 
            bool committed = false; 
            if (!this.ExplicitCommit)
            { 
                //commit change and let the commit change code do the revert
                committed = Commit(false);

                //reset the error icon if we didn't get to set it in the commit 
                if (!committed || this.IsIndependentExpression)
                { 
                    this.EditingState = EditingState.Idle; 
                    // Switch the control back to a textbox -
                    // but give it the text from the editor (textbox should be bound to the Text property, so should 
                    // automatically be filled with the correct text, from when we set the Text property earlier)
                    if (!this.ContentTemplate.Equals((DataTemplate)FindResource("textblock")))
                    {
                        this.ContentTemplate = (DataTemplate)FindResource("textblock"); 
                    }
                } 
            } 

            //raise EditorLostLogical focus - in case when some clients need to do explicit commit 
            this.RaiseEvent(new RoutedEventArgs(ExpressionTextBox.EditorLostLogicalFocusEvent, this));
        }

        private void KillValidator() 
        {
            if (validator != null) 
            { 
                this.validator.CancelAsync();
                this.validator.Dispose(); 
                this.validator = null;
            }
        }
 
        internal static bool ShouldGenerateExpression(string oldText, string newText)
        { 
            return newText != null && !string.Equals(newText, oldText) && !(oldText == null && newText.Equals(string.Empty)); 
        }
 
        private bool Commit(bool isExplicitCommit)
        {
            bool committed = false;
            //only generate and validate the expression when when we don't require explicit commit change 
            //or when the commit is explicit
            if (!this.ExplicitCommit || isExplicitCommit) 
            { 
                // Generate and validate the expression.
                // Get the text from the snapshot and set it to the Text property 
                this.previousText = null;
                // In VS
                if (this.expressionEditorInstance != null)
                { 
                    this.previousText = this.Text;
                    this.Text = this.expressionEditorInstance.GetCommittedText(); 
                } 
                // In rehost
                else 
                {
                    if (this.Expression != null)
                    {
                        Activity expression = this.Expression.GetCurrentValue() as Activity; 
                        // if expression is null, GetExpressionString will return null
                        this.previousText = ExpressionHelper.GetExpressionString(expression, this.OwnerActivity); 
                    } 
                    else
                    { 
                        this.previousText = null;
                    }
                }
 
                // If the Text is null, or equal to the previous value, or changed from null to empty, don't bother generating the expression
                // We still need to generate the expression when it is changed from other value to EMPTY however - otherwise 
                // the case where you had an expression (valid or invalid), then deleted the whole thing will not be evaluated. 
                if (ShouldGenerateExpression(this.previousText, this.Text))
                { 
                    GenerateExpression();
                    committed = true;
                }
            } 
            if (!this.ContentTemplate.Equals((DataTemplate)FindResource("textblock")))
            { 
                this.ContentTemplate = (DataTemplate)FindResource("textblock"); 
            }
            return committed; 
        }

        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
        { 
            base.OnPreviewMouseLeftButtonDown(e);
 
            if (this.Context != null) 
            {
                ExpressionSelection expressionSelection = new ExpressionSelection(this.Expression); 
                this.Context.Items.SetValue(expressionSelection);
            }
        }
 
        public void BeginEdit()
        { 
            //am i loaded? is current template a textblock? 
            if (this.isExpressionLoaded || null == this.Expression)
            { 
                this.isBeginEditPending = false;
                this.IsReadOnly = false;
                if (this.IsLoaded && this.ContentTemplate.Equals(this.FindResource("textblock")))
                { 
                    //get control's content presenter
                    ContentPresenter presenter = VisualTreeUtils.GetTemplateChild(this); 
                    if (null != presenter) 
                    {
                        //and look for the loaded textblock 
                        TextBlock tb = (TextBlock)this.ContentTemplate.FindName("expresionTextBlock", presenter);
                        if (null != tb)
                        {
                            //now - give focus to the textblock - it will trigger OnGotTextBlockFocus event, which eventually 
                            //swithc ETB into expression editing mode.
                            tb.Focus(); 
                        } 
                    }
                } 
            }
            else
            {
                this.isBeginEditPending = true; 
            }
        } 
 
        internal bool HasAggregateFocus()
        { 
            bool result = false;

            if (this.IsLoaded)
            { 
                if (this.expressionEditorInstance != null)
                { 
                    result = (this.hostControl != null && this.hostControl.IsFocused) || this.expressionEditorInstance.HasAggregateFocus; 
                }
                else 
                {
                    result = !this.IsKeyboardFocused && this.IsKeyboardFocusWithin;
                }
            } 

            return result; 
        } 

        void OnTextBlockMouseLeftButtonDown(object sender, RoutedEventArgs e) 
        {
            if (!this.IsReadOnly)
            {
                TextBlock textBlock = sender as TextBlock; 
                if (textBlock != null)
                { 
                    Keyboard.Focus(textBlock); 
                }
            } 
        }

        void OnGotTextBlockFocus(object sender, RoutedEventArgs e)
        { 
            if (this.Context == null)
            { 
                return; 
            }
 
            DesignerView designerView = this.Context.Services.GetService();

            if (!designerView.IsMultipleSelectionMode)
            { 
                TextBlock textBlock = sender as TextBlock;
                bool isInReadOnlyMode = this.IsReadOnly; 
                if (this.Context != null) 
                {
                    ReadOnlyState readOnlyState = this.Context.Items.GetValue(); 
                    isInReadOnlyMode |= readOnlyState.IsReadOnly;
                }
                if (null != textBlock)
                { 
                    this.blockHeight = textBlock.ActualHeight;
                    this.blockHeight = Math.Max(this.blockHeight, textBlock.MinHeight); 
                    this.blockHeight = Math.Min(this.blockHeight, textBlock.MaxHeight); 
                    this.blockWidth = textBlock.ActualWidth;
                    this.blockWidth = Math.Max(this.blockWidth, textBlock.MinWidth); 
                    this.blockWidth = Math.Min(this.blockWidth, textBlock.MaxWidth);

                    // If it's already an editor, don't need to switch it/reload it (don't create another editor/grid if we don't need to)
                    // Also don't create editor when we are in read only mode 
                    if (this.ContentTemplate.Equals((DataTemplate)FindResource("textblock")) && !isInReadOnlyMode)
                    { 
                        if (this.Context != null) 
                        {
                            // Get the ExpressionEditorService 
                            this.expressionEditorService = this.Context.Services.GetService();
                        }

                        // If the service exists, use the editor template - else switch to the textbox template 
                        if (this.expressionEditorService != null)
                        { 
                            this.PerfProvider.WorkflowDesignerExpressionEditorLoadStart(); 
                            this.ContentTemplate = (DataTemplate)FindResource("editor");
                        } 
                        else
                        {
                            this.ContentTemplate = (DataTemplate)FindResource("textbox");
                        } 
                    }
                } 
 
                if (!isInReadOnlyMode)
                { 
                    //disable the error icon
                    this.StartValidator();
                    this.EditingState = EditingState.Editing;
                    e.Handled = true; 
                }
            } 
        } 

        void OnGotEditingFocus(object sender, RoutedEventArgs e) 
        {
            //disable the error icon
            this.EditingState = EditingState.Editing;
            this.StartValidator(); 
        }
 
        // This method is called when the editor data template is loaded - when the editor data template 
        // is loaded, create the editor session and the expression editor
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
            Justification = "CreateExpressionEditor is part of a public API. Propagating exceptions might lead to VS crash.")]
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "CreateExpressionEditor is part of a public API. Propagating exceptions might lead to VS crash.")]
        void OnEditorLoaded(object sender, RoutedEventArgs e) 
        {
            // If the service exists, create an expression editor and add it to the grid - else switch to the textbox data template 
            if (this.expressionEditorService != null) 
            {
                Border border = (Border)sender; 
                // Get the references and variables in scope
                AssemblyContextControlItem assemblies = (AssemblyContextControlItem)this.Context.Items.GetValue(typeof(AssemblyContextControlItem));
                List declaredVariables = VariableHelper.FindUniqueVariablesInScope(this.OwnerActivity);
                declaredVariables.AddRange(VariableHelper.FindActionHandlerVariables(this.OwnerActivity)); 

                //if expression editor is loaded in the WF which is hosted within ActivityBuilderHelper, there is a need to pickup defined arguments 
                //and feed them as variables, so intelisense can include them 
                if (null != this.OwnerActivity && ActivityBuilderHelper.IsActivityBuilderType(this.OwnerActivity.Root))
                { 
                    ModelTreeManager treeManager = ((IModelTreeItem)this.OwnerActivity).ModelTreeManager;
                    //call ActivityBuilderHelper.GetVariables - it will create a collection of Variable - each variable corresponds to a specific argument
                    declaredVariables.AddRange(
                        ActivityBuilderHelper.GetVariables(this.OwnerActivity.Root). 
                        //create a fake model item implementation - there is no need to store that model item anywhere in the model tree, it is requirement
                        //of the expression editor interface to pass instances of model items wrapping variables, rather than actual variables 
                        Select(entry => new FakeModelItemImpl(treeManager, typeof(Variable), entry, null))); 
                }
                ImportedNamespaceContextItem importedNamespaces = this.Context.Items.GetValue(); 
                importedNamespaces.EnsureInitialized(this.Context);
                //if the expression text is empty and the expression type is set, then we initialize the text to prompt text
                if (String.Equals(this.ExpressionText, string.Empty, StringComparison.OrdinalIgnoreCase) && this.ExpressionType != null)
                { 
                    this.Text = TypeToPromptTextConverter.GetPromptText(this.ExpressionType);
                } 
 
                //this is a hack
                this.blockWidth = Math.Max(this.ActualWidth - 8, 0);  //8 is the margin 
                if (this.HasErrors)
                {
                    this.blockWidth = Math.Max(this.blockWidth - 16, 0); //give 16 for error icon
                } 
                try
                { 
                    if (this.ExpressionType != null) 
                    {
                        this.expressionEditorInstance = this.expressionEditorService.CreateExpressionEditor(assemblies, importedNamespaces, declaredVariables, this.Text, this.ExpressionType, new Size(this.blockWidth, this.blockHeight)); 
                    }
                    else
                    {
                        this.expressionEditorInstance = this.expressionEditorService.CreateExpressionEditor(assemblies, importedNamespaces, declaredVariables, this.Text, new Size(this.blockWidth, this.blockHeight)); 
                    }
                } 
                catch (Exception ex) 
                {
                    Trace.WriteLine(ex.Message); 
                }

                if (this.expressionEditorInstance != null)
                { 
                    try
                    { 
                        this.expressionEditorInstance.VerticalScrollBarVisibility = this.VerticalScrollBarVisibility; 
                        this.expressionEditorInstance.HorizontalScrollBarVisibility = this.HorizontalScrollBarVisibility;
 
                        this.expressionEditorInstance.AcceptsReturn = this.AcceptsReturn;
                        this.expressionEditorInstance.AcceptsTab = this.AcceptsTab;

                        // Add the expression editor to the text panel, at column 1 
                        this.hostControl = this.expressionEditorInstance.HostControl;
 
                        // Subscribe to this event to change scrollbar visibility on the fly for auto, and to resize the hostable editor 
                        // as necessary
                        this.expressionEditorInstance.LostAggregateFocus += new EventHandler(OnEditorLostAggregateFocus); 
                        this.expressionEditorInstance.Closing += new EventHandler(OnEditorClosing);

                        // Set up Hostable Editor properties
                        this.expressionEditorInstance.MinLines = this.MinLines; 
                        this.expressionEditorInstance.MaxLines = this.MaxLines;
 
                        this.expressionEditorInstance.HostControl.Style = (Style)FindResource("editorStyle"); 

                        border.Child = this.hostControl; 
                        this.expressionEditorInstance.Focus();
                    }
                    catch (KeyNotFoundException ex)
                    { 
                        Debug.Fail("Unable to find editor with the following editor name: " + this.editorName, ex.Message);
                    } 
                } 
            }
 
            if (this.expressionEditorInstance == null)
            {
                this.ContentTemplate = (DataTemplate)FindResource("textbox");
            } 
            this.PerfProvider.WorkflowDesignerExpressionEditorLoaded();
        } 
 
        void OnEditorClosing(object sender, EventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            {
                //these events are expected to be unregistered during lost focus event, but
                //we are unregistering them during unload just in case.  Ideally we want to 
                //do this in the CloseExpressionEditor method
                this.expressionEditorInstance.LostAggregateFocus -= new EventHandler(OnEditorLostAggregateFocus); 
 
                this.expressionEditorInstance.Closing -= new EventHandler(OnEditorClosing);
                this.expressionEditorInstance = null; 
            }
            Border boarder = this.hostControl.Parent as Border;
            if (boarder != null)
            { 
                boarder.Child = null;
            } 
            this.hostControl = null; 
            this.editorName = null;
 
        }

        void OnEditorLostAggregateFocus(object sender, EventArgs e)
        { 
            this.DoLostFocus();
        } 
 
        //void BindEditorProperties()
        //{ 
        //    this.hostControl.SetBinding(Control.ContextMenuProperty, "ContextMenu");
        //    this.hostControl.SetBinding(Control.FlowDirectionProperty, "FlowDirection");
        //    this.hostControl.SetBinding(Control.FontFamilyProperty, "FontFamily");
        //    this.hostControl.SetBinding(Control.FontSizeProperty, "FontSize"); 
        //    this.hostControl.SetBinding(Control.FontStretchProperty, "FontStretch");
        //    this.hostControl.SetBinding(Control.FontStyleProperty, "FontStyle"); 
        //    this.hostControl.SetBinding(Control.FontWeightProperty, "FontWeight"); 
        //    this.hostControl.SetBinding(Control.HeightProperty, "Height");
        //    this.hostControl.SetBinding(Control.LanguageProperty, "Language"); 
        //    this.hostControl.SetBinding(Control.SnapsToDevicePixelsProperty, "SnapsToDevicePixels");
        //}

        // This method is called when the editor data template is unloaded - when the editor data template 
        // is unloaded, close the editor session and set the expression editor and editor session to null
        void OnEditorUnloaded(object sender, RoutedEventArgs e) 
        { 
            // Blank the editorSession and the expressionEditor so as not to use up memory
            // Destroy both as you can only ever spawn one editor per session 
            if (this.expressionEditorInstance != null)
            {
                //if we are unloaded during editing, this means we got here by someone clicking breadcrumb, we should try to commit
                if (this.EditingState == EditingState.Editing) 
                {
                    this.Commit(false); 
                } 
                this.expressionEditorInstance.Close();
            } 
        }

        // This method is to give focus and set the caret position when the TextBox DataTemplate is loaded
        void OnTextBoxLoaded(object sender, RoutedEventArgs e) 
        {
            TextBox textbox = (TextBox)sender; 
            textbox.ContextMenu = null; 

            //to workaround a but in the TextBox layout code 
            Binding binding = new Binding();
            binding.Source = this;
            binding.Path = new PropertyPath(ExpressionTextBox.TextProperty);
            binding.Mode = BindingMode.TwoWay; 
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
 
            textbox.SetBinding(TextBox.TextProperty, binding); 

            // Set the cursor to correct text position 
            int index = GetCharacterIndexFromPoint(textbox);

            textbox.SelectionStart = index;
            textbox.SelectionLength = 0; 

            textbox.Focus(); 
        } 

        // This method is to workaround the fact that textbox.GetCharacterIndexFromPoint returns the caret 
        // to the left of the character... Thus you can never get the caret after the last character in the
        // expression string.
        int GetCharacterIndexFromPoint(TextBox textbox)
        { 
            Point position = Mouse.GetPosition(textbox);
            int index = textbox.GetCharacterIndexFromPoint(position, false); 
 
            if (index < 0)
            { 
                // May have clicked outside the text area, get the index of nearest char
                index = textbox.GetCharacterIndexFromPoint(position, true);
                if (index < 0)
                { 
                    index = 0;
                } 
 
                // Adjust the cursor position if we clicked to the right of returned character
                Rect charRect = textbox.GetRectFromCharacterIndex(index, true); 
                if (position.X > charRect.Left + charRect.Width / 2)
                {
                    index++;
                } 
            }
 
            return index; 
        }
 
        static void ValidateExpression(ExpressionTextBox etb)
        {
            string errorMessage;
            if (etb.DoValidation(new ExpressionValidationContext(etb), out errorMessage)) 
            {
                etb.UpdateValidationError(errorMessage); 
            } 
        }
 
        static void OnLinesChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            ExpressionTextBox textBox = (ExpressionTextBox)dependencyObject;
 
            if (textBox.MinLines > textBox.MaxLines)
            { 
                textBox.MaxLines = textBox.MinLines; 
            }
        } 

        static void OnTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            ExpressionTextBox textBox = (ExpressionTextBox)dependencyObject; 

            if (textBox.ExpressionEditorService != null && textBox.expressionEditorInstance != null) 
            { 
                textBox.expressionEditorInstance.Text = textBox.Text;
            } 

        }

        static void OnOwnerModelItemChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
        {
            ExpressionTextBox textBox = (ExpressionTextBox)dependencyObject; 
 
            textBox.InitializeContext();
            textBox.OnPathToArgumentChanged(textBox.PathToArgument); 
        }

        public IExpressionEditorService ExpressionEditorService
        { 
            get { return this.expressionEditorService; }
        } 
 
        internal string Text
        { 
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
 
        internal string ExpressionText
        { 
            get { return (string)GetValue(ExpressionTextProperty); } 
            set { SetValue(ExpressionTextProperty, value); }
        } 

        public string HintText
        {
            get { return (string)GetValue(HintTextProperty); } 
            set { SetValue(HintTextProperty, value); }
        } 
 
        [Fx.Tag.KnownXamlExternal]
        public ModelItem Expression 
        {
            get { return (ModelItem)GetValue(ExpressionTextBox.ExpressionProperty); }
            set { SetValue(ExpressionTextBox.ExpressionProperty, value); }
        } 

        public Type ExpressionType 
        { 
            get { return (Type)GetValue(ExpressionTextBox.ExpressionTypeProperty); }
            set { SetValue(ExpressionTextBox.ExpressionTypeProperty, value); } 
        }

        [Fx.Tag.KnownXamlExternal]
        public ModelItem OwnerActivity 
        {
            get { return (ModelItem)GetValue(ExpressionTextBox.OwnerActivityProperty); } 
            set { SetValue(ExpressionTextBox.OwnerActivityProperty, value); } 
        }
 
        internal ValidationState ValidationState
        {
            get { return (ValidationState)GetValue(ExpressionTextBox.ValidationStateProperty); }
            set { SetValue(ExpressionTextBox.ValidationStateProperty, value); } 
        }
 
        public bool UseLocationExpression 
        {
            get { return (bool)GetValue(ExpressionTextBox.UseLocationExpressionProperty); } 
            set { SetValue(ExpressionTextBox.UseLocationExpressionProperty, value); }
        }

        public ScrollBarVisibility VerticalScrollBarVisibility 
        {
            get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); } 
            set { SetValue(VerticalScrollBarVisibilityProperty, value); } 
        }
 
        public ScrollBarVisibility HorizontalScrollBarVisibility
        {
            get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); }
            set { SetValue(HorizontalScrollBarVisibilityProperty, value); } 
        }
 
        public int MaxLines 
        {
            get { return (int)GetValue(MaxLinesProperty); } 
            set { SetValue(MaxLinesProperty, value); }
        }

        public int MinLines 
        {
            get { return (int)GetValue(MinLinesProperty); } 
            set { SetValue(MinLinesProperty, value); } 
        }
 
        public bool ExplicitCommit
        {
            get { return (bool)GetValue(ExplicitCommitProperty); }
            set { SetValue(ExplicitCommitProperty, value); } 
        }
 
        internal bool HasErrors 
        {
            get 
            {
                bool hasErrors = false;
                if (this.EditingState == EditingState.Idle
                    && !this.IsIndependentExpression) 

                { 
                    if (this.Expression != null && this.ValidationService != null && this.ValidationService.ValidationStateProperty != null) 
                    {
                        ValidationState state = this.ValidationService.ValidationStateProperty.Getter(this.Expression); 
                        hasErrors = state == ValidationState.Error;
                    }
                }
                else 
                {
                    hasErrors = this.HasValidationError; 
                } 
                return hasErrors;
            } 
        }

        internal string ErrorMessage
        { 
            get
            { 
                string errorMessage = string.Empty; 

                if (this.EditingState == EditingState.Idle && !this.IsIndependentExpression) 
                {
                    if (this.Expression != null && this.ValidationService != null && this.ValidationService.ValidationStateProperty != null)
                    {
                        errorMessage = this.ValidationService.ValidationMessageProperty.Getter(this.Expression); 
                    }
                } 
                else 
                {
                    errorMessage = this.ValidationErrorMessage; 
                }
                return errorMessage;
            }
        } 

        internal EditingState EditingState 
        { 
            get { return (EditingState)GetValue(EditingStateProperty); }
            set { SetValue(EditingStateProperty, value); } 
        }

        internal bool HasValidationError
        { 
            get { return (bool)GetValue(HasValidationErrorProperty); }
            set { SetValue(HasValidationErrorProperty, value); } 
        } 

        internal string ValidationErrorMessage 
        {
            get { return (string)GetValue(ValidationErrorMessageProperty); }
            set { SetValue(ValidationErrorMessageProperty, value); }
        } 

        public string PathToArgument 
        { 
            get { return (string)GetValue(PathToArgumentProperty); }
            set { SetValue(PathToArgumentProperty, value); } 
        }

        public bool IsSupportedExpression
        { 
            get { return (bool)GetValue(IsSupportedExpressionProperty); }
            set { SetValue(IsSupportedExpressionProperty, value); } 
        } 

        public string DefaultValue 
        {
            get { return (string)GetValue(DefaultValueProperty); }
            set { SetValue(DefaultValueProperty, value); }
        } 

        public bool AcceptsReturn 
        { 
            get { return (bool)GetValue(AcceptsReturnProperty); }
            set { SetValue(AcceptsReturnProperty, value); } 
        }

        public bool AcceptsTab
        { 
            get { return (bool)GetValue(AcceptsTabProperty); }
            set { SetValue(AcceptsTabProperty, value); } 
        } 

        public bool IsReadOnly 
        {
            get { return (bool)GetValue(IsReadOnlyProperty); }
            set { SetValue(IsReadOnlyProperty, value); }
        } 

        internal bool IsIndependentExpression 
        { 
            get { return (bool)GetValue(IsIndependentExpressionProperty); }
            set { SetValue(IsIndependentExpressionProperty, value); } 
        }

        EditingContext Context
        { 
            get
            { 
                if (this.context == null) 
                {
                    if (this.OwnerActivity != null) 
                    {
                        InitializeContext();
                    }
                } 
                return this.context;
            } 
        } 

        DesignerPerfEventProvider PerfProvider 
        {
            get
            {
                if (this.perfProvider == null && this.Context != null) 
                {
                    perfProvider = this.Context.Services.GetService(); 
                } 
                return this.perfProvider;
            } 
        }

        ValidationService ValidationService
        { 
            get
            { 
                if (this.Context != null) 
                {
                    return this.Context.Services.GetService(); 
                }
                else
                {
                    return null; 
                }
            } 
        } 

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")]
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")]
        internal void GenerateExpression() 
        {
            Activity valueExpression = null; 
 
            // If the text is null we don't need to bother generating the expression (this would be the case the
            // first time you enter an ETB. We still need to generate the expression when it is EMPTY however - otherwise 
            // the case where you had an expression (valid or invalid), then deleted the whole thing will not be evaluated.
            if (this.Text != null)
            {
                using (ModelEditingScope scope = this.OwnerActivity.BeginEdit(SR.PropertyChangeEditingScopeDescription)) 
                {
                    this.EditingState = EditingState.Validating; 
                    // we set the expression to null 
                    // a) when the expressionText is empty AND it's a reference expression or
                    // b) when the expressionText is empty AND the DefaultValue property is null 
                    if (this.Text.Length == 0 &&
                        (this.UseLocationExpression || this.DefaultValue == null))
                    {
                        valueExpression = null; 
                    }
                    else 
                    { 
                        if (this.Text.Length == 0)
                        { 
                            this.Text = this.DefaultValue;
                        }
                        valueExpression = CreateVBExpression();
                    } 
                    CreateExpressionModelItem(valueExpression);
                    scope.Complete(); 
                } 
            }
        } 

        void OnValidationCompleted(object sender, EventArgs e)
        {
            if (this.EditingState != EditingState.Editing) 
            {
                if (this.Expression != null && this.ValidationService != null && this.ValidationService.ValidationStateProperty != null) 
                { 
                    this.ValidationState = this.ValidationService.ValidationStateProperty.Getter(this.Expression);
                } 

                this.EditingState = EditingState.Idle;
            }
        } 

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")] 
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")] 
        private void CreateExpressionModelItem(object valueExpression)
        {
            // try to wrap the droppedObject in  a ModelItem.
            ModelItem expressionModelItem = null; 
            if (valueExpression != null)
            { 
                ModelServiceImpl modelService = (ModelServiceImpl)this.Context.Services.GetService(); 
                expressionModelItem = modelService.WrapAsModelItem(valueExpression);
                expressionModelItem.PropertyChanged += this.OnExpressionModelItemChanged; 
                this.boundedExpression = expressionModelItem;
            }
            try
            { 
                this.internalModelItemChange = true;
                this.EditingState = EditingState.Validating; 
                SetValue(ExpressionProperty, expressionModelItem); 
            }
            catch (Exception err) 
            {
                Trace.WriteLine(string.Format(CultureInfo.CurrentUICulture, "{0}\r\n{1}", err.Message, err.StackTrace));
                this.internalModelItemChange = false;
            } 
        }
 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")]
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule", 
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")]
        private Activity CreateVBExpression()
        {
            Activity valueExpression = null; 
            if (this.OwnerActivity != null)
            { 
                ExpressionValidationContext validationContext = new ExpressionValidationContext(this); 

                Type expReturnType = null; 
                string newExpressionText = null;
                SourceExpressionException compileErrorMessages;

                try 
                {
                    VisualBasicSettings settings = null; 
                    valueExpression = CreateVBExpression(validationContext, out newExpressionText, out expReturnType, out compileErrorMessages, out settings); 

                    if (settings != null) 
                    {
                        Fx.Assert(this.Context != null, "editing context cannot be null");
                        //merge with import designer
                        foreach (VisualBasicImportReference reference in settings.ImportReferences) 
                        {
                            ImportDesigner.AddImport(reference.Import, this.Context); 
                        } 
                    }
 
                    if (!string.IsNullOrEmpty(newExpressionText))
                    {
                        this.previousText = this.Text;
                        this.Text = newExpressionText; 
                    }
                } 
                catch (Exception err) 
                {
                    //if the VisualBasicDesignerHelper were able to resolve the type we use that 
                    if (expReturnType == null)
                    {
                        //if not we try to use the expression type
                        expReturnType = this.ExpressionType; 
                    }
 
                    //if expression type is also null, the we use object 
                    if (expReturnType == null)
                    { 
                        expReturnType = typeof(object);
                    }

                    valueExpression = ExpressionHelper.CreateExpression(expReturnType, this.Text, UseLocationExpression, validationContext.ParserContext); 

                    Trace.WriteLine(string.Format(CultureInfo.CurrentUICulture, "{0}\r\n{1}", err.Message, err.StackTrace)); 
                } 
                this.ExpressionText = this.Text;
            } 
            else
            {
                // If the OwnerActivity is null, do not try to compile the expression otherwise VS will crash
                // Inform the user that OwnerActivity is null (i.e. there is a error in their code) 
                Trace.WriteLine("ExpressionTextBox OwnerActivity is null.");
            } 
            return valueExpression; 
        }
 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")]
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")] 
        private static Activity CreateVBExpression(ExpressionValidationContext context, out string newExpressionText, out Type expReturnType, out SourceExpressionException compileErrorMessages, out VisualBasicSettings vbSettings)
        { 
            expReturnType = null; 
            newExpressionText = null;
            compileErrorMessages = null; 
            vbSettings = null;

            //try easy way first - look if there is a type converer which supports convertsion between expression type and string
            ActivityWithResult literal = null; 
            try
            { 
                if (!context.UseLocationExpression) 
                {
                    literal = ExpressionHelper.TryCreateLiteral(context.ExpressionType, context.ExpressionText, context.ParserContext); 
                }

                if (literal != null)
                { 
                    //need to get new expression text - converter might have changed its format, and we want it to be up to date
                    IValueSerializableExpression serializableExpression = literal as IValueSerializableExpression; 
                    Fx.Assert(serializableExpression != null, "the expression has to be a Literal<>, which should be IValueSerializableExpression"); 
                    if (serializableExpression.CanConvertToString(context.ParserContext))
                    { 
                        bool shouldBeQuoted = typeof(string) == context.ExpressionType || typeof(Uri) == context.ExpressionType;

                        //whether string begins and ends with quotes '"'. also, if there are
                        //more quotes within than those begining and ending ones, do not bother with literal - assume this is an expression. 
                        bool isQuotedString = shouldBeQuoted &&
                                context.ExpressionText.StartsWith("\"", StringComparison.CurrentCulture) && 
                                context.ExpressionText.EndsWith("\"", StringComparison.CurrentCulture) && 
                                context.ExpressionText.IndexOf("\"", 1, StringComparison.CurrentCulture) == context.ExpressionText.Length - 1;
                        var formatString = isQuotedString ? "\"{0}\"" : "{0}"; 
                        newExpressionText = string.Format(CultureInfo.InvariantCulture, formatString, serializableExpression.ConvertToString(context.ParserContext));
                    }
                }
            } 
            //conversion failed - do nothing, let VB compiler take care of the expression
            catch 
            { 
            }
 
            Activity valueExpression = literal;

            if (null == valueExpression)
            { 
                if (!context.UseLocationExpression)
                { 
                    //Compile for validation. 
                    valueExpression = VisualBasicDesignerHelper.CreatePrecompiledVisualBasicValue(context.ExpressionType, context.ExpressionText, context.ParserContext.Namespaces, context.ReferencedAssemblies, context.ParserContext, out expReturnType, out compileErrorMessages, out vbSettings);
                } 
                else
                {
                    //Compile for validation.
                    valueExpression = VisualBasicDesignerHelper.CreatePrecompiledVisualBasicReference(context.ExpressionType, context.ExpressionText, context.ParserContext.Namespaces, context.ReferencedAssemblies, context.ParserContext, out expReturnType, out compileErrorMessages, out vbSettings); 
                }
            } 
            return valueExpression; 
        }
 
        static void OnExpressionTypeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            ExpressionTextBox etb = obj as ExpressionTextBox;
            Fx.Assert (etb != null, "Sender must be an ETB"); 
            //for independent expressions, when the type changes, we need to validate the expressions
            if (etb.initialized 
                && etb.IsIndependentExpression 
                && etb.EditingState == EditingState.Idle)
            { 
                ValidateExpression(etb);
            }
        }
 
        static void OnUseLocationExpressionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        { 
            ExpressionTextBox etb = obj as ExpressionTextBox; 
            Fx.Assert(etb != null, "Sender must be an ETB");
            //for independent expressions, when the type changes, we need to validate the expressions 
            if (etb.initialized
                && etb.IsIndependentExpression
                && etb.EditingState == EditingState.Idle
                && etb.OwnerActivity != null) 
            {
                ValidateExpression(etb); 
            } 
        }
 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "The entered expression might be invalid and may throw on deserialization. Propagating exception might lead to VS crash")]
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "The entered expression might be invalid and may throw on deserialization. Propagating exception might lead to VS crash")] 
        static void OnExpressionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        { 
            ExpressionTextBox ctrl = (ExpressionTextBox)obj; 
            ModelItem oldExpression = e.OldValue as ModelItem;
            if (oldExpression != null) 
            {
                oldExpression.PropertyChanged -= ctrl.OnExpressionModelItemChanged;
            }
            ModelItem expression = e.NewValue as ModelItem; 
            if (expression != null && expression != ctrl.boundedExpression)
            { 
                expression.PropertyChanged += ctrl.OnExpressionModelItemChanged; 
            }
 
            try
            {
                ctrl.boundedExpression = expression;
 
                ctrl.OnExpressionChanged();
            } 
            catch (Exception err) 
            {
                //if context is set - use error reporting 
                if (null != ctrl.Context)
                {
                    ctrl.Context.Items.SetValue(new ErrorItem() { Message = err.Message, Details = err.ToString() });
                } 
                //otherwise - fallback to message box
                else 
                { 
                    MessageBox.Show(err.ToString(), err.Message);
                } 
            }

        }
 
        void expressionModelItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
        { 
            ModelItem item = sender as ModelItem; 
            if (item != null)
            { 
                if (e.PropertyName.Equals("ExpressionText", StringComparison.Ordinal))
                {
                    this.OnExpressionChanged();
                } 
            }
        } 
 
        static void OnPathToArgumentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        { 
            ExpressionTextBox ctrl = (ExpressionTextBox)obj;
            ctrl.OnPathToArgumentChanged((string)e.NewValue);
        }
 
        static void OnIsIndependentExpressionChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        { 
            ExpressionTextBox etb = dependencyObject as ExpressionTextBox; 
            Fx.Assert(etb != null, "Sender must be an ETB");
 
            //if this is an independent expression, we need to initialize the validation error because validation service will not validate it
            if (etb.initialized
                && etb.IsIndependentExpression
                && etb.EditingState == EditingState.Idle) 
            {
                ValidateExpression(etb); 
            } 
        }
 
        void UpdateValidationState()
        {
            if (this.Expression != null && this.ValidationService != null && this.ValidationService.ValidationStateProperty != null)
            { 
                this.ValidationState = this.ValidationService.ValidationStateProperty.Getter(this.Expression);
            } 
            else 
            {
                this.ValidationState = ValidationState.Valid; 
            }
        }

        //We need to react to OnExpressionChanged, since there might be multiple ExpressionTextBoxes(ETB) associated to a single Expression. 
        //All the ETBs should be updated if the value in any of the ETBs is changed.
        void OnExpressionChanged() 
        { 
            if (!this.internalModelItemChange)
            { 
                if (this.Expression == null)
                {
                    //new expression is null - there is no text, no previous text, erros should be clear as well as error message
                    this.Text = string.Empty; 
                    this.previousText = this.Text;
                    this.ExpressionText = null; 
                    this.ValidationState = ValidationState.Valid; 
                }
                else 
                {
                    this.UpdateValidationState();

                    object expressionObject = this.Expression.GetCurrentValue(); 
                    Activity expression = null;
                    String expressionString = null; 
 
                    //create parser context - do not pass ownerActivity - it might be null at this time
                    ParserContext context = new ParserContext(); 
                    expression = expressionObject as Activity;
                    //get the expression text out of expression - in case of non-VB expression, context may be populated with
                    //extra namespace information
                    expressionString = ExpressionHelper.GetExpressionString(expression, context); 
                    if (expressionString != null)
                    { 
                        Fx.Assert(expression != null, "if expression is null, expressionString should also be null"); 
                        Type expressionType = expression.GetType();
                        Type expressionArgumentType = expressionType.IsGenericType ? expressionType.GetGenericArguments()[0] : typeof(object); 

                        bool isValid = false;
                        bool isLiteral = false;
 
                        //try to figure out what kind of expression are we dealing with
                        while (null != expressionType) 
                        { 
                            //check if expression is literal expression
                            if (expressionType.IsGenericType && typeof(Literal<>) == expressionType.GetGenericTypeDefinition()) 
                            {
                                isLiteral = true;
                            }
                            //expression must be of type Activity 
                            if (expressionType.IsGenericType && typeof(Activity<>) == expressionType.GetGenericTypeDefinition())
                            { 
                                isValid = true; 
                                break;
                            } 
                            expressionType = expressionType.BaseType;
                        }

 
                        if (!isValid)
                        { 
                            throw FxTrace.Exception.AsError(new NotSupportedException()); 
                        }
 
                        this.Text = expressionString;
                        this.ExpressionText = expressionString;
                        this.previousText = this.Text;
 
                        //if expression is a literal, which is not supported, delegate a call to regenerate it as expression
                        if (isLiteral && !ExpressionHelper.CanTypeBeSerializedAsLiteral( expressionArgumentType )) 
                        { 
                            //call should be postponed until whole ux is loaded.
                            this.Dispatcher.BeginInvoke(new Action(() => { this.GenerateExpression(); }), DispatcherPriority.ApplicationIdle); 
                        }
                    }
                    else
                    { 
                        //We won't handle non-VB expressions
                        this.IsSupportedExpression = false; 
                        this.HintText = SR.UnsupportedExpressionHintText; 
                    }
 
                    this.isExpressionLoaded = true;
                    if (this.isBeginEditPending)
                    {
                        this.BeginEdit(); 
                    }
                } 
            } 
            internalModelItemChange = false;
        } 

        void OnPathToArgumentChanged(string pathAsString)
        {
            this.expressionModelProperty = null; 
            this.expressionConverter = null;
            if (!string.IsNullOrEmpty(pathAsString) && null != this.OwnerActivity) 
            { 
                string[] path = pathAsString.Split('.');
                if (path.Length > 0) 
                {
                    this.expressionModelProperty = this.OwnerActivity.Properties[path[0]];
                    for (int i = 1; i < path.Length; ++i)
                    { 
                        if (null != this.expressionModelProperty && null != this.expressionModelProperty.Value)
                        { 
                            this.expressionModelProperty = this.expressionModelProperty.Value.Properties[path[i]]; 
                        }
                        else 
                        {
                            this.expressionModelProperty = null;
                            break;
                        } 
                    }
                } 
            } 
            if (null != this.expressionModelProperty)
            { 
                this.expressionConverter = ((ModelPropertyImpl)this.expressionModelProperty).PropertyDescriptor.Converter;
            }
            this.InitializeHintText();
        } 

        void InitializeHintText() 
        { 
            DescriptionAttribute customHint = null;
            if (this.expressionModelProperty != null && this.expressionModelProperty.Attributes.Count != 0) 
            {
                customHint = this.expressionModelProperty.Attributes.
                    OfType().
                    FirstOrDefault(); 
            }
            this.HintText = (null == customHint || string.IsNullOrEmpty(customHint.Description) ? 
                (string.Equals(this.HintText, SR.ExpressionDefaultText) ? SR.ExpressionDefaultText : this.HintText) : customHint.Description); 

            string hint = this.HintText.Trim(new char[] { '<', '>' }); 
            this.SetValue(AutomationProperties.HelpTextProperty, hint);
        }

        void InitializeContext() 
        {
            if (this.context == null) 
            { 
                ModelItem modelItem = this.OwnerActivity;
                Fx.Assert(modelItem != null, "OwnerActivity is not set before calling InitializeContext()"); 

                if (null != modelItem)
                {
                    this.context = modelItem.GetEditingContext(); 
                    if (this.ValidationService != null)
                    { 
                        this.ValidationService.ValidationCompleted += this.OnValidationCompleted; 
                        this.UpdateValidationState();
                    } 
                }
            }
        }
 
        #region Command Handlers
 
        void OnCommitCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            string currentText = this.Text; 
            if (this.expressionEditorInstance != null)
            {
                currentText = this.expressionEditorInstance.Text;
                if (!string.IsNullOrEmpty(currentText)) 
                {
                    currentText = currentText.Trim(); 
                } 
            }
            //we dont need to commit change if currentText and previousText is the same 
            //null and empty should be considered equal in this context
            e.CanExecute = !string.Equals(currentText, this.previousText) &&
                           !(string.IsNullOrEmpty(currentText) && string.IsNullOrEmpty(this.previousText));
            e.Handled = true; 
        }
 
        void OnCommitCommandExecute(object sender, ExecutedRoutedEventArgs e) 
        {
            this.Commit(true); 
            e.Handled = true;
        }

        void OnExpressionTextBoxLoaded(object sender, RoutedEventArgs e) 
        {
            this.InitializeHintText(); 
 
            //if this is an independent expression, we need to initialize the validation error because validation service will not validate it
            if (this.IsIndependentExpression) 
            {
                ValidateExpression(this);
            }
 
            this.initialized = true;
        } 
 
        void OnExpressionTextBoxUnloaded(object sender, RoutedEventArgs e)
        { 
            if (this.ValidationService != null)
            {
                this.ValidationService.ValidationCompleted -= this.OnValidationCompleted;
            } 
            KillValidator();
 
            if (this.boundedExpression != null) 
            {
                this.boundedExpression.PropertyChanged -= this.OnExpressionModelItemChanged; 
            }
        }

        void OnCompleteWordCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
 
            if (this.expressionEditorInstance != null) 
            {
 
                e.CanExecute = this.expressionEditorInstance.CanCompleteWord();
                e.Handled = true;
            }
            else 
            {
                e.Handled = false; 
            } 
        }
        void OnGlobalIntellisenseCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {

            if (this.expressionEditorInstance != null)
            { 
                e.CanExecute = this.expressionEditorInstance.CanGlobalIntellisense();
                e.Handled = true; 
            } 
            else
            { 
                e.Handled = false;
            }
        }
 
        void OnParameterInfoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        { 
 
            if (this.expressionEditorInstance != null)
            { 
                e.CanExecute = this.expressionEditorInstance.CanParameterInfo();
                e.Handled = true;
            }
            else 
            {
                e.Handled = false; 
            } 
        }
 
        void OnQuickInfoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.expressionEditorInstance != null)
            { 
                e.CanExecute = this.expressionEditorInstance.CanQuickInfo();
                e.Handled = true; 
            } 
            else
            { 
                e.Handled = false;
            }
        }
 
        void OnIncreaseFilterLevelCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null) 
            {
                e.CanExecute = this.expressionEditorInstance.CanIncreaseFilterLevel(); 
                e.Handled = true;
            }
            else
            { 
                e.Handled = false;
            } 
        } 

        void OnDecreaseFilterLevelCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if (this.expressionEditorInstance != null)
            {
                e.CanExecute = this.expressionEditorInstance.CanDecreaseFilterLevel(); 
                e.Handled = true;
            } 
            else 
            {
                e.Handled = false; 
            }
        }

        void OnCutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if (this.expressionEditorInstance != null) 
            { 
                e.CanExecute = this.expressionEditorInstance.CanCut();
                e.Handled = true; 
            }
            else
            {
                e.Handled = false; 
            }
        } 
 
        void OnCompleteWordCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            {
                e.Handled = this.expressionEditorInstance.CompleteWord();
            } 
            else
            { 
                e.Handled = false; 
            }
 
        }

        void OnGlobalIntellisenseCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            { 
                e.Handled = this.expressionEditorInstance.GlobalIntellisense(); 
            }
            else 
            {
                e.Handled = false;
            }
 
        }
 
        void OnParameterInfoCommandExecute(object sender, ExecutedRoutedEventArgs e) 
        {
            if (this.expressionEditorInstance != null) 
            {
                e.Handled = this.expressionEditorInstance.ParameterInfo();
            }
            else 
            {
                e.Handled = false; 
            } 

        } 

        void OnQuickInfoCommandExecute(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.expressionEditorInstance != null) 
            {
                e.Handled = this.expressionEditorInstance.QuickInfo(); 
            } 
            else
            { 
                e.Handled = false;
            }

        } 

        void OnDecreaseFilterLevelCommandExecute(object sender, ExecutedRoutedEventArgs e) 
        { 
            if (this.expressionEditorInstance != null)
            { 
                e.Handled = this.expressionEditorInstance.DecreaseFilterLevel();
            }
            else
            { 
                e.Handled = false;
            } 
 
        }
 
        void OnIncreaseFilterLevelCommandExecute(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.expressionEditorInstance != null)
            { 
                e.Handled = this.expressionEditorInstance.IncreaseFilterLevel();
            } 
            else 
            {
                e.Handled = false; 
            }

        }
 
        void OnCutCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null) 
            {
                e.Handled = this.expressionEditorInstance.Cut(); 
            }
            else
            {
                e.Handled = false; 
            }
        } 
 
        void OnCopyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            {
                e.CanExecute = this.expressionEditorInstance.CanCopy();
                e.Handled = true; 
            }
            else 
            { 
                e.Handled = false;
            } 
        }

        void OnCopyCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            { 
                e.Handled = this.expressionEditorInstance.Copy(); 
            }
            else 
            {
                e.Handled = false;
            }
        } 

        void OnPasteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        { 
            if (this.expressionEditorInstance != null)
            { 
                e.CanExecute = this.expressionEditorInstance.CanPaste();
                e.Handled = true;
            }
            else 
            {
                e.Handled = false; 
            } 
        }
 
        void OnPasteCommandExecute(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.expressionEditorInstance != null)
            { 
                e.Handled = this.expressionEditorInstance.Paste();
            } 
            else 
            {
                e.Handled = false; 
            }
        }

        void OnUndoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if (this.expressionEditorInstance != null) 
            { 
                e.CanExecute = this.expressionEditorInstance.CanUndo();
                e.Handled = true; 
            }
            else
            {
                e.Handled = false; 
            }
        } 
 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "Catch all execeptions to prevent crash.")] 
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
            Justification = "Catch all execeptions to prevent crash.")]
        void OnUndoCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            { 
                try 
                {
                    e.Handled = this.expressionEditorInstance.Undo(); 
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message); 
                }
            } 
            else 
            {
                e.Handled = false; 
            }
        }

        void OnRedoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if (this.expressionEditorInstance != null) 
            { 
                e.CanExecute = this.expressionEditorInstance.CanRedo();
                e.Handled = true; 
            }
            else
            {
                e.Handled = false; 
            }
        } 
 
        void OnRedoCommandExecute(object sender, ExecutedRoutedEventArgs e)
        { 
            if (this.expressionEditorInstance != null)
            {
                e.Handled = this.expressionEditorInstance.Redo();
            } 
            else
            { 
                e.Handled = false; 
            }
        } 

        void OnHelpExecute(object sender, ExecutedRoutedEventArgs e)
        {
            IIntegratedHelpService help = this.Context.Services.GetService(); 
            if (help != null)
            { 
                help.ShowHelpFromKeyword(HelpKeywords.ExpressionEditorPage); 
            }
            else 
            {
                System.Diagnostics.Process.Start(SR.DefaultHelpUrl);
            }
        } 

        #endregion 
 
        static void OnHintTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        { 
            if (!string.Equals(SR.ExpressionDefaultText, e.NewValue) && !string.Equals(e.OldValue, e.NewValue))
            {
                ((ExpressionTextBox)sender).InitializeHintText();
            } 
        }
 
        static void OnAcceptsReturnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ExpressionTextBox etb = sender as ExpressionTextBox; 
            if (etb != null && etb.expressionEditorInstance != null)
            {
                etb.expressionEditorInstance.AcceptsReturn = (bool)e.NewValue;
            } 
        }
 
        static void OnAcceptsTabChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ExpressionTextBox etb = sender as ExpressionTextBox; 
            if (etb != null && etb.expressionEditorInstance != null)
            {
                etb.expressionEditorInstance.AcceptsTab = (bool)e.NewValue;
            } 
        }
 
        void StartValidator() 
        {
            if (this.validator == null) 
            {
                this.validator = new BackgroundWorker();
                this.validator.WorkerReportsProgress = true;
                this.validator.WorkerSupportsCancellation = true; 

                this.validator.DoWork += delegate(object obj, DoWorkEventArgs args) 
                { 
                    BackgroundWorker worker = obj as BackgroundWorker;
                    if (worker.CancellationPending) 
                    {
                        args.Cancel = true;
                        return;
                    } 
                    ExpressionValidationContext validationContext = args.Argument as ExpressionValidationContext;
                    if (validationContext != null) 
                    { 
                        string errorMessage;
                        if (DoValidation(validationContext, out errorMessage)) 
                        {
                            worker.ReportProgress(0, errorMessage);
                        }
 
                        //sleep
                        if (worker.CancellationPending) 
                        { 
                            args.Cancel = true;
                            return; 
                        }

                        Thread.Sleep(ValidationWaitTime);
                        args.Result = validationContext; 
                    }
 
                }; 

                this.validator.RunWorkerCompleted += delegate(object obj, RunWorkerCompletedEventArgs args) 
                {
                    if (!args.Cancelled)
                    {
                        ExpressionValidationContext validationContext = args.Result as ExpressionValidationContext; 
                        if (validationContext != null)
                        { 
                            Dispatcher.BeginInvoke(new Action((target)=>{ 
                                //validator could be null by the time we try to validate again or
                                //if it's already busy 
                                if (this.validator != null && !this.validator.IsBusy)
                                {
                                    target.Update(this);
                                    this.validator.RunWorkerAsync(target); 
                                }
                            }), validationContext); 
                        } 
                    }
                }; 

                this.validator.ProgressChanged += delegate(object obj, ProgressChangedEventArgs args)
                {
                    string error = args.UserState as string; 
                    Dispatcher.BeginInvoke(new Action(UpdateValidationError), error);
                }; 
 
                this.validator.RunWorkerAsync(new ExpressionValidationContext(this));
            } 
        }

        //perform one validation synchronously
        //return value indicates whether errorMessage is updated. 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
            Justification = "The entered expression might be invalid and may throw on deserialization. Propagating exception might lead to VS crash")] 
        [SuppressMessage("Reliability", "Reliability108:IsFatalRule", 
            Justification = "The entered expression might be invalid and may throw on deserialization. Propagating exception might lead to VS crash")]
        bool DoValidation(ExpressionValidationContext validationContext, out string errorMessage) 
        {
            Fx.Assert(validationContext != null, "only work when context is not null");
            errorMessage = null;
 
            //validate
            //if the text is empty we clear the error message 
            if (string.IsNullOrEmpty(validationContext.ExpressionText)) 
            {
                errorMessage = null; 
                return true;
            }
            // if the expression text is different from the last time we run the validation we run the validation
            else if (!string.Equals(validationContext.ExpressionText, validationContext.ValidatedExpressionText)) 
            {
                Type expReturnType = null; 
                string newExpressionText = null; 
                SourceExpressionException compileErrorMessages = null;
                VisualBasicSettings settings = null; 
                try
                {
                    CreateVBExpression(validationContext, out newExpressionText, out expReturnType, out compileErrorMessages, out settings);
                    if (compileErrorMessages != null) 
                    {
                        errorMessage = compileErrorMessages.Message; 
                    } 
                }
                catch (Exception err) 
                {
                    errorMessage = err.Message;
                }
 
                return true;
            } 
 
            return false;
        } 

        void UpdateValidationError(string errorMessage)
        {
            if (!string.IsNullOrEmpty(errorMessage)) 
            {
                //report error 
                this.HasValidationError = true; 
                this.ValidationErrorMessage = errorMessage;
            } 
            else
            {
                this.HasValidationError = false;
                this.ValidationErrorMessage = null; 
            }
        } 
 
        private class ExpressionValidationContext
        { 
            internal ParserContext ParserContext { get; set; }
            internal Type ExpressionType { get; set; }
            internal String ExpressionText { get; set; }
            internal EditingContext EditingContext { get; set; } 
            internal String ValidatedExpressionText { get; set; }
            internal bool UseLocationExpression { get; set; } 
 
            internal ExpressionValidationContext(ExpressionTextBox etb)
            { 
                Update(etb);
            }

            internal void Update(ExpressionTextBox etb) 
            {
                Fx.Assert(etb.OwnerActivity != null, "Owner Activity is null"); 
                this.EditingContext = etb.OwnerActivity.GetEditingContext(); 

                //setup ParserContext 
                this.ParserContext = new ParserContext(etb.OwnerActivity)
                {
                    //callee is a ExpressionTextBox
                    Instance = etb, 
                    //pass property descriptor belonging to epression's model property (if one exists)
                    PropertyDescriptor = (null != etb.expressionModelProperty ? ((ModelPropertyImpl)etb.expressionModelProperty).PropertyDescriptor : null), 
                }; 

                this.ExpressionType = etb.ExpressionType; 
                this.ValidatedExpressionText = this.ExpressionText;
                if (etb.expressionEditorInstance != null)
                {
                    this.ExpressionText = etb.expressionEditorInstance.Text; 
                }
                else 
                { 
                    this.ExpressionText = etb.Text;
                } 
                this.UseLocationExpression = etb.UseLocationExpression;
            }

            internal IEnumerable ReferencedAssemblies 
            {
                get 
                { 
                    Fx.Assert(this.EditingContext != null, "ModelItem.Context = null");
                    AssemblyContextControlItem assemblyContext = this.EditingContext.Items.GetValue(); 
                    if (assemblyContext != null)
                    {
                        return assemblyContext.AllAssemblyNamesInContext;
                    } 
                    return null;
                } 
            } 
        }
    } 

    internal sealed class LineToHeightConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
        {
            double convertedValue = Double.NaN; 
            bool isDefault = true; 

            // Calculate the height for the textblock as ExpressionTextBox exposes lines properties, 
            // and TextBlock doesn't have lines properties.
            FontFamily fontFamily = values.OfType().FirstOrDefault();
            int lines = values.OfType().FirstOrDefault();
            double[] doubleArray = values.OfType().ToArray(); 

            if (doubleArray.Length == 2) 
            { 
                double height = doubleArray[0]; // The first element of the array is going to be the height
                double fontSize = doubleArray[1]; // The seconed element of the array is going to be the fontSize 

                // 0.0 is default for MinHeight, PositiveInfinity is default for MaxHeight
                if (string.Equals(parameter as string, "MinHeight"))
                { 
                    isDefault = (height == 0.0);
                } 
                else if (string.Equals(parameter as string, "MaxHeight")) 
                {
                    isDefault = (double.IsPositiveInfinity(height)); 
                }

                // If the height value we are evaluating is default, use Lines for sizing...
                // If no heights (height or lines) have been explicitly specified, we would rather default the height 
                // as if the Line was 1 - so use the line heights, rather than 0.0 and/or PositiveInfinity.
                if (isDefault) 
                { 
                    double lineHeight = fontSize * fontFamily.LineSpacing;
 
                    if (fontFamily != null)
                    {
                        convertedValue = lineHeight * (double)lines + 4;
                    } 
                }
                else 
                { 
                    convertedValue = height;
                } 
            }

            return convertedValue;
        } 

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
        { 
            throw FxTrace.Exception.AsError(new NotSupportedException());
        } 
    }

    internal sealed class ValidationStateToErrorConverter : IMultiValueConverter
    { 

        #region IMultiValueConverter Members 
 
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        { 
            ExpressionTextBox etb = values[0] as ExpressionTextBox;
            if (values[0] == DependencyProperty.UnsetValue || etb == null)
            {
                return false; 
            }
            return etb.HasErrors; 
        } 

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
        {
            throw FxTrace.Exception.AsError(new NotImplementedException());
        }
 
        #endregion
    } 
 
    internal sealed class ValidationErrorMessageConverter : IMultiValueConverter
    { 
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        { 
            ExpressionTextBox etb = values[0] as ExpressionTextBox;
            if (values[0] == DependencyProperty.UnsetValue || etb == null) 
            { 
                return false;
            } 
            return etb.ErrorMessage;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
        {
            throw FxTrace.Exception.AsError(new NotImplementedException()); 
        } 

        #endregion 
    }

    internal sealed class TypeToPromptTextConverter : IValueConverter
    { 
        #region IValueConverter Members
 
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
        {
            return TypeToPromptTextConverter.GetPromptText(value); 
        }

        internal static string GetPromptText(object value)
        { 
            Type expressionType = value as Type;
            if (value == DependencyProperty.UnsetValue || expressionType == null || !expressionType.IsValueType) 
            { 
                return "Nothing";
            } 
            else
            {
                return Activator.CreateInstance(expressionType).ToString();
            } 
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
        {
            throw FxTrace.Exception.AsError(new NotSupportedException()); 
        }

        #endregion
    } 

 
    public enum EditingState 
    {
        Editing, 
        Validating,
        Idle
    }
} 

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