PropertyPanel.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / Base / Core / Internal / PropertyEditing / PropertyPanel.cs / 1305376 / PropertyPanel.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing
{ 
    using System;
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Media;
 
    // 
    // PropertyPanel is a simplified version of a horizontal StackPanel that we use for PropertyContainer
    // visuals in lieu of Grid, which was too heavy-weight and bogging down perf.  It exposes a property,
    // LastChildWidth, that specifies the forced width of the last child in the panel.  All other 
    // children are stacked on the left and eat up the remainder of the space left on the panel.
    // 
    // The panel also deals with drawing compartments for itself and the last child and it deals with 
    // visually nesting sub-properties based on their depth (Level).
    //  
    internal class PropertyPanel : Panel
    {

        // LastChildWidth DP 

        public static readonly DependencyProperty OutlineBrushProperty = 
            DependencyProperty.Register("OutlineBrush", 
            typeof(Brush),
            typeof(PropertyPanel), 
            new FrameworkPropertyMetadata((Brush)null,
            FrameworkPropertyMetadataOptions.AffectsRender |
            FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender));
 
        public static readonly DependencyProperty SelectionBrushProperty =
            DependencyProperty.Register("SelectionBrush", 
            typeof(Brush), 
            typeof(PropertyPanel),
            new FrameworkPropertyMetadata((Brush)null, 
            FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender));

        public static readonly DependencyProperty OutlineThicknessProperty =
            DependencyProperty.Register("OutlineThickness", 
            typeof(double),
            typeof(PropertyPanel), 
            new FrameworkPropertyMetadata((double)1, 
            FrameworkPropertyMetadataOptions.AffectsRender));
 
        public static readonly DependencyProperty IgnoreFirstChildBackgroundProperty =
            DependencyProperty.Register("IgnoreFirstChildBackground",
            typeof(bool),
            typeof(PropertyPanel), 
            new FrameworkPropertyMetadata(
            false, 
            FrameworkPropertyMetadataOptions.AffectsRender)); 

        public static DependencyProperty LastChildWidthProperty = DependencyProperty.Register( 
            "LastChildWidth",
            typeof(double),
            typeof(PropertyPanel),
            new FrameworkPropertyMetadata( 
            (double)0,
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender)); 
 
        public static DependencyProperty LevelProperty = DependencyProperty.Register(
            "Level", 
            typeof(int),
            typeof(PropertyPanel),
            new FrameworkPropertyMetadata(
            (int)0, 
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
 
        public static DependencyProperty LevelIndentProperty = DependencyProperty.Register( 
            "LevelIndent",
            typeof(double), 
            typeof(PropertyPanel),
            new FrameworkPropertyMetadata(
            (double)13,
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)); 

        //  
        // Gets or sets the pixel width of the last child added into this panel. 
        // 
        public double LastChildWidth 
        {
            get { return (double)this.GetValue(LastChildWidthProperty); }
            set { this.SetValue(LastChildWidthProperty, value); }
        } 

 
 
        // Level DP
 
        // 
        // Gets or sets the indentation level for the first child in this panel.  Levels are
        // measured in ints, with 0 = no indentation, 1 = 1st sub-property, ...
        // The actual amount of space taken up by each level is controled by LevelIndent property 
        // 
        public int Level 
        { 
            get { return (int)this.GetValue(LevelProperty); }
            set { this.SetValue(LevelProperty, value); } 
        }


 
        // LevelIndent DP
 
        //  
        // Gets or sets the pixel width that the first child is indented for each level that
        // it belongs to 
        // 
        public double LevelIndent
        {
            get { return (double)this.GetValue(LevelIndentProperty); } 
            set { this.SetValue(LevelIndentProperty, value); }
        } 
 

 
        // OutlineBrush DP

        // 
        // Gets or sets the line brush to use for the panel compartments 
        // 
        public Brush OutlineBrush 
        { 
            get { return (Brush)GetValue(OutlineBrushProperty); }
            set { SetValue(OutlineBrushProperty, value); } 
        }


 
        // SelectionBrush DP
 
        //  
        // Gets or sets the brush to be used as the background for everything but the last
        // element in the panel 
        // 
        public Brush SelectionBrush
        {
            get { return (Brush)GetValue(SelectionBrushProperty); } 
            set { SetValue(SelectionBrushProperty, value); }
        } 
 

 
        // OutlineThickness DP

        // 
        // Gets or sets the line thickness for the panel compartments (not as Thickness, but 
        // instead as a simple double)
        //  
        public double OutlineThickness 
        {
            get { return (double)GetValue(OutlineThicknessProperty); } 
            set { SetValue(OutlineThicknessProperty, value); }
        }

 

        // IgnoreFirstChildBackground DP 
 
        // 
        // Gets or sets a flag indicating whether the SelectionBrush background should 
        // or should not be applied to the first child of the panel
        // 
        public bool IgnoreFirstChildBackground
        { 
            get { return (bool)GetValue(IgnoreFirstChildBackgroundProperty); }
            set { SetValue(IgnoreFirstChildBackgroundProperty, value); } 
        } 

 

        // Stacks the children to the left, leaving LastChildWidth amount of space for the last child
        protected override Size MeasureOverride(Size availableSize)
        { 

            double lastChildWidth = Math.Max(0, this.LastChildWidth); 
            double indent = this.LevelIndent * this.Level; 
            double availableWidth = Math.Max(0, availableSize.Width - lastChildWidth - indent);
            int childrenCount = InternalChildren.Count; 
            int lastIndex = childrenCount - 1;
            Size actualSize = new Size();

            for (int i = 0; i < childrenCount; i++) 
            {
                UIElement child = InternalChildren[i]; 
 
                if (i == lastIndex)
                { 
                    InternalChildren[i].Measure(new Size(lastChildWidth, availableSize.Height));
                }
                else
                { 
                    InternalChildren[i].Measure(new Size(availableWidth, availableSize.Height));
                } 
 
                availableWidth -= child.DesiredSize.Width;
                //Compute the actual size for the propertypanel 
                actualSize.Height = Math.Max(actualSize.Height, child.DesiredSize.Height);
                actualSize.Width += child.DesiredSize.Width;
            }
 
            return actualSize;
        } 
 
        // Stacks the children to the left, leaving LastChildWidth amount of space for the last child
        protected override Size ArrangeOverride(Size finalSize) 
        {

            double lastChildWidth = Math.Max(0, this.LastChildWidth);
            double indent = this.LevelIndent * this.Level; 
            double availableWidth = Math.Max(0, finalSize.Width - lastChildWidth - indent);
            double left = indent; 
            int childrenCount = InternalChildren.Count; 
            int lastIndex = childrenCount - 1;
 
            for (int i = 0; i < childrenCount; i++)
            {

                UIElement child = InternalChildren[i]; 
                double desiredWidth = child.DesiredSize.Width;
                if (i == lastIndex) 
                { 
                    child.Arrange(new Rect(Math.Max(0, finalSize.Width - lastChildWidth), 0, lastChildWidth, finalSize.Height));
                } 
                else
                {
                    child.Arrange(new Rect(left, 0, Math.Min(desiredWidth, availableWidth), finalSize.Height));
                } 

                left += desiredWidth; 
                availableWidth -= desiredWidth; 
                availableWidth = Math.Max(0, availableWidth);
            } 

            return finalSize;
        }
 
        // Custom renders compartments and dividers
        protected override void OnRender(DrawingContext dc) 
        { 

            Size renderSize = this.RenderSize; 
            Brush outlineBrush = this.OutlineBrush;
            double outlineThickness = this.OutlineThickness;
            double halfThickness = outlineThickness / 2.0;
            double dividerRight = Math.Max(0, this.LastChildWidth); 
            double dividerLeft = renderSize.Width - dividerRight - outlineThickness;
 
            Brush selectionBrush = this.SelectionBrush; 

            if (selectionBrush != null) 
            {
                bool ignoreFirstChildBackground = this.IgnoreFirstChildBackground;
                double firstChildWidth = 0;
 
                if (ignoreFirstChildBackground && this.Children.Count > 0)
                { 
                    firstChildWidth = this.Children[0].RenderSize.Width; 
                }
 
                dc.DrawRectangle(selectionBrush, null, new Rect(
                    firstChildWidth,
                    0,
                    Math.Max(dividerLeft - firstChildWidth, 0), 
                    renderSize.Height));
            } 
 
            base.OnRender(dc);
 
            // Use Guidelines to avoid anti-aliasing (fuzzy border lines)
            dc.PushGuidelineSet(new GuidelineSet(
                // X coordinates for guidelines (vertical lines)
                new double[] { 0, dividerLeft, dividerLeft + outlineThickness, renderSize.Width - outlineThickness, renderSize.Width }, 
                // Y coordinates for guidelines (horizontal lines)
                new double[] { 0, renderSize.Height - outlineThickness, renderSize.Height })); 
 
            Pen outlinePen = new Pen(outlineBrush, outlineThickness);
 
            // Bottom edge
            dc.DrawLine(
                outlinePen,
                new Point(0, renderSize.Height - halfThickness), 
                new Point(renderSize.Width, renderSize.Height - halfThickness));
 
            // Top edge 
            dc.DrawLine(
                outlinePen, 
                new Point(0, 0 - halfThickness),
                new Point(renderSize.Width, 0 - halfThickness));

            // Right edge 
            dc.DrawLine(
                outlinePen, 
                new Point(renderSize.Width - halfThickness, 0), 
                new Point(renderSize.Width - halfThickness, renderSize.Height));
 
            // Divider
            dc.DrawLine(
                outlinePen,
                new Point(dividerLeft + halfThickness, 0), 
                new Point(dividerLeft + halfThickness, renderSize.Height));
 
            dc.Pop(); 
        }
    } 
}

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

10808,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/PropertyInspector.xaml.cs/1305376/PropertyInspector.xaml.cs,4/26/2010 8:54:39 AM,39389
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing
{ 
    using System;
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Windows;
    using System.Windows.Automation.Peers;
    using System.Windows.Controls;
    using System.Windows.Media; 
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes; 
    using System.Windows.Threading; 

    using System.Activities.Presentation; 
    using System.Activities.Presentation.Model;
    using View = System.Activities.Presentation.View;
    using System.Activities.Presentation.PropertyEditing;
    using System.Runtime; 

    using System.Activities.Presentation.Internal.PropertyEditing.Automation; 
    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.ValueEditors; 
    using System.Activities.Presentation.Internal.PropertyEditing.Model;
    using ModelUtilities=System.Activities.Presentation.Internal.PropertyEditing.Model.ModelUtilities; 
    using System.Activities.Presentation.Internal.PropertyEditing.Resources;
    using System.Activities.Presentation.Internal.PropertyEditing.Selection;
    using System.Activities.Presentation.Internal.PropertyEditing.State;
    using System.Text; 

    //  
    // The main control that acts as the PropertyInspector 
    // 
    [SuppressMessage(FxCop.Category.Naming, "CA1724:TypeNamesShouldNotMatchNamespaces", 
        Justification = "Code imported from Cider; keeping changes to a minimum as it impacts xaml files as well")]
    partial class PropertyInspector :
        INotifyPropertyChanged
    { 

        private static readonly Size DesiredIconSize = new Size(40, 40); 
 
        private View.Selection _displayedSelection;
        private View.Selection _lastNotifiedSelection; 
        private ModelItem _lastParent;

        private bool _ignoreSelectionNameChanges;
 
        private List _pendingTransactions = new List();
        private PropertyValueEditorCommandHandler _defaultCommandHandler; 
        private IStateContainer _sessionStateContainer; 

        private SelectionPath _lastSelectionPath; 
        private bool _objectSelectionInitialized;

        private bool _disposed;
        private bool _isReadOnly; 

        private ContextItemManager designerContextItemManager; 
 
        // Map between currently displayed category editors and the names of the categories they belong to
        private Dictionary _activeCategoryEditors = new Dictionary(); 

        // 
        // Basic ctor
        //  
        // FxCop complains this.DataContext, which is somewhat bogus
        [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
        public PropertyInspector() 
        {
            this.DataContext = this; 

            HookIntoCommands();

            this.InitializeComponent(); 

            //Handle the commit and cancel keys within the property inspector 
            ValueEditorUtils.SetHandlesCommitKeys(this, true); 

            _propertyToolBar.CurrentViewManagerChanged += new EventHandler(OnCurrentViewManagerChanged); 
        }

        // 
        // Event fired when the IsInAlphaView changes as a result of some 
        // user or internal interaction.  When IsInAlphaView is set by the
        // external host, this event will not and should not be fired. 
        //  
        public event EventHandler RootViewModified;
 
        public event PropertyChangedEventHandler PropertyChanged;

        [SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly", Justification = "No need for a Setter")]
        public ContextItemManager DesignerContextItemManager 
        {
            set 
            { 
                this.designerContextItemManager = value;
                this.designerContextItemManager.Subscribe(this.OnSelectionChanged); 
            }
        }

        //  
        // Gets a value indicating whether the selected object Name should be read-only
        //  
        public bool IsInfoBarNameReadOnly 
        {
            get { 
                return _displayedSelection == null || _displayedSelection.SelectionCount != 1;
            }
        }
 
        // 
        // Gets the selection name to display 
        //  
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Propagating the error might cause VS to crash")]
        [SuppressMessage("Reliability", "Reliability108", Justification = "Propagating the error might cause VS to crash")] 
        public string SelectionName
        {
            get {
                if (_displayedSelection == null || _displayedSelection.SelectionCount == 0) 
                {
                    return null; 
                } 

                if (_displayedSelection.SelectionCount == 1) 
                {
                    return _displayedSelection.PrimarySelection.Name;
                }
 
                return System.Activities.Presentation.Internal.Properties.Resources.PropertyEditing_MultipleObjectsSelected;
            } 
            set { 
                if (_disposed)
                { 
                    return;
                }

                if (CanSetSelectionName(_displayedSelection)) 
                {
                    ModelItem selection = _displayedSelection.PrimarySelection; 
                    Fx.Assert(selection != null, "PrimarySelection should not be null"); 

                    try 
                    {
                        _ignoreSelectionNameChanges = true;

                        using (ModelEditingScope change = selection.BeginEdit(System.Activities.Presentation.Internal.Properties.Resources.PropertyEditing_NameChangeUndoText)) 
                        {
                            if (string.IsNullOrEmpty(value)) 
                            { 
                                // Null with cause ClearValue to be called in the base implementation on the NameProperty
                                selection.Name = null; 
                            }
                            else
                            {
                                selection.Name = value; 
                            }
 
                            if (change != null) 
                                change.Complete();
                        } 
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine(e.ToString()); 

                        ErrorReporting.ShowErrorMessage(e.Message); 
                    } 
                    finally
                    { 
                        _ignoreSelectionNameChanges = false;
                    }

                    OnPropertyChanged("SelectionName"); 
                }
                else 
                { 
                    Debug.Fail("Shouldn't be able to set a selection name if no or more than one object is selected.");
                } 
            }
        }

        //  
        // Gets the icon for the selection
        //  
        public object SelectionIcon 
        {
            get { 
                if (_displayedSelection == null || _displayedSelection.SelectionCount == 0)
                {
                    return null;
                } 

                if (_displayedSelection.SelectionCount == 1 || AreHomogenous(_displayedSelection.SelectedObjects)) 
                { 

                    if (_displayedSelection.SelectionCount == 1) 
                    {

                        Visual selectedVisual = _displayedSelection.PrimarySelection.View as Visual;
                        // We dont want to show tooltips for elements that derive from "Window" class. 
                        // But we do want to show it for DesignTimeWindow, hence we check the View, so that modelItem returns the correct value
                        // for designtimewindow. 
                        if (selectedVisual != null && !typeof(Window).IsAssignableFrom(_displayedSelection.PrimarySelection.View.GetType())) 
                        {
                            // Show a small preview of the selected single object 
                            VisualBrush controlBrush = new VisualBrush(selectedVisual);
                            controlBrush.Stretch = Stretch.Uniform;
                            Rectangle rect = new Rectangle();
                            rect.Width = DesiredIconSize.Width; 
                            rect.Height = DesiredIconSize.Height;
                            rect.DataContext = string.Empty; 
 
                            // If the control's parent is RTLed, then the VisualBrush "mirrors" the text.
                            // so apply "mirror" transform to "negate" the mirroring. 
                            FrameworkElement curElement = selectedVisual as FrameworkElement;
                            FrameworkElement parentElement = curElement.Parent as FrameworkElement;
                            if (parentElement != null && parentElement.FlowDirection == FlowDirection.RightToLeft)
                            { 
                                ScaleTransform mirrorTransform = new ScaleTransform(-1, 1);
                                mirrorTransform.CenterX = rect.Width / 2; 
                                mirrorTransform.CenterY = rect.Height / 2; 
                                controlBrush.Transform = mirrorTransform;
                            } 
                            rect.Fill = controlBrush;
                            return rect;
                        }
                        else 
                        {
                            // The selected object is not a visual, so show a non-designable object icon 
                            return GetEmbeddedImage("NonDesignableSelection.png"); 
                        }
                    } 

                    // Show mutliple-selection of the same type icon
                    return GetEmbeddedImage("MultiSelectionSameType.png");
                } 

                // Show multiple-selection of different types icon 
                return GetEmbeddedImage("MultiSelectionDifferentType.png"); 
            }
        } 

        // 
        // Gets the Type name for the current selection
        //  
        public string SelectionTypeName
        { 
            get { 
                if (_displayedSelection == null || _displayedSelection.SelectionCount == 0)
                { 
                    return null;
                }

                if (_displayedSelection.SelectionCount == 1 || AreHomogenous(_displayedSelection.SelectedObjects)) 
                {
                    return GetStringRepresentation(_displayedSelection.PrimarySelection.ItemType); 
                } 

                return System.Activities.Presentation.Internal.Properties.Resources.PropertyEditing_MultipleTypesSelected; 
            }
        }

        static string GetStringRepresentation(Type type) 
        {
            return TypeNameHelper.GetDisplayName(type, true); 
        } 

        // Property View 

        // 
        // Gets the state that should be persisted while the host is
        // running, but discarded when the host shuts down. 
        // 
        public object SessionState 
        { 
            get {
                // Don't instantiate the SessionStateContainer until 
                // CategoryList has been instantiated.  Otherwise, we would
                // get an invalid container.
                if (_categoryList == null)
                { 
                    return null;
                } 
 
                return SessionStateContainer.RetrieveState();
            } 
            set {
                // Don't instantiate the SessionStateContainer until
                // CategoryList has been instantiated.  Otherwise, we would
                // get an invalid container. 
                if (_categoryList == null || value == null)
                { 
                    return; 
                }
 
                SessionStateContainer.RestoreState(value);

                _objectSelectionInitialized = false;
            } 
        }
 
        public bool IsReadOnly 
        {
            get { return this._isReadOnly; } 
            internal set
            {
                this._isReadOnly = value;
                this._categoryList.Opacity = this._isReadOnly ? 0.8 : 1.0; 
                this._categoryList.ToolTip = this._isReadOnly ? this.FindResource("editingDisabledHint") : null;
                this.OnPropertyChanged("IsReadOnly"); 
            } 
        }
 
        // 
        // Gets or sets a flag indicating whether the root PropertyInspector
        // control is in alpha-view.  We isolate this state from any other
        // to make VS integration easier. 
        // 
        public bool IsInAlphaView 
        { 
            get { return _propertyToolBar.IsAlphaViewSelected; }
            set { _propertyToolBar.IsAlphaViewSelected = value; } 
        }

        internal TextBlock SelectionTypeLabel
        { get { return _typeLabel; } } 
        //internal TextBlock SelectionNameLabel
        //{ get { return _nameLabel; } } 
        //internal StringEditor SelectionNameEditor 
        //{ get { return _nameEditor; } }
        internal PropertyToolBar PropertyToolBar 
        { get { return _propertyToolBar; } }
        internal TextBlock NoSearchResultsLabel
        { get { return _noSearchResultsLabel; } }
        internal TextBlock UninitializedLabel 
        { get { return _uninitializedLabel; } }
        internal CategoryList CategoryList 
        { get { return _categoryList; } } 

        private SelectionPath LastSelectionPath 
        {
            get { return _lastSelectionPath; }
            set { _lastSelectionPath = value; }
        } 

        private IStateContainer SessionStateContainer 
        { 
            get {
                if (_categoryList == null) 
                {
                    return null;
                }
 
                if (_sessionStateContainer == null)
                { 
                    _sessionStateContainer = new AggregateStateContainer( 
                        PropertyStateContainer.Instance,
                        _categoryList, 
                        new SelectionPathStateContainer(this),
                        PropertyActiveEditModeStateContainer.Instance,
                        PropertyViewManagerStateContainer.Instance);
                } 

                return _sessionStateContainer; 
            } 
        }
 
        // IPropertyInspectorState

        internal void Dispose()
        { 
            _disposed = true;
            DisassociateAllProperties(); 
            UpdateSelectionPropertyChangedEventHooks(_displayedSelection, null); 
            _displayedSelection = null;
            _defaultCommandHandler.Dispose(); 
            _defaultCommandHandler = null;
        }

        private void HookIntoCommands() 
        {
            // Use a helper classes to handle all the standard PI commands 
            _defaultCommandHandler = new PropertyValueEditorCommandHandler(this); 
        }
 
        // 
        // Marks all shown properties as disassociated which disables all modifications
        // done to them through the PI model objects.
        //  
        private void DisassociateAllProperties()
        { 
            if (_categoryList != null && _categoryList.IsLoaded) 
            {
                foreach (ModelCategoryEntry category in _categoryList) 
                {
                    category.MarkAllPropertiesDisassociated();
                }
            } 
        }
 
        // Properties 

        private void OnCurrentViewManagerChanged(object sender, EventArgs e) 
        {
            this.RefreshPropertyList(false);

            // Isolate the current view of the root PropertyInspector into 
            // its own separate flag and event to appease the VS ----s
            // 
            if (this.RootViewModified != null) 
            {
                RootViewModified(null, EventArgs.Empty); 
            }
        }

        private void RefreshPropertyList(bool attachedOnly) 
        {
            UpdateCategories(_lastNotifiedSelection, attachedOnly); 
            UpdateCategoryEditors(_lastNotifiedSelection); 

            // 
            // The first time SelectionChanges, there is nothing selected, so don't store the
            // current property selected.  It would just overwrite the selection path that we
            // received from SelectionPathStateContainer, which is not what we want.
            // 
            if (_objectSelectionInitialized)
            { 
                LastSelectionPath = _categoryList.SelectionPath; 
            }
 
            _objectSelectionInitialized = true;

            //
            // Call UpdateSelectedProperty() _after_ the UI renders.  We need to set PropertySelection.IsSelected 
            // property on a templated visual objects (CategoryContainer, PropertyContainer) and those may not exist yet.
            // 
            Dispatcher.BeginInvoke(DispatcherPriority.Render, new UpdateSelectedPropertyInvoker(UpdateSelectedProperty), _lastNotifiedSelection); 
        }
 

        // Selection Logic

        // SelectionPathStateContainer 

        //  
        // Called externally whenever selection changes 
        // 
        // New selection 
        public void OnSelectionChanged(View.Selection selection)
        {
            _lastNotifiedSelection = selection;
            RefreshSelection(); 
        }
 
        //  
        // Called when visibility of the PropertyBrowserPane changes and the
        // PropertyInspector may be showing a stale selection.  This method is identical 
        // to OnSelectionChanged() but with no new selection instance introduced.
        // 
        public void RefreshSelection()
        { 
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new MethodInvoker(OnSelectionChangedIdle));
        } 
 
        // Updates PI when the application becomes Idle (perf optimization)
        private void OnSelectionChangedIdle() 
        {
            if (AreSelectionsEquivalent(_lastNotifiedSelection, _displayedSelection))
            {
                return; 
            }
 
            if (!VisualTreeUtils.IsVisible(this)) 
            {
                return; 
            }

            // Change the SelectedControlFlowDirectionRTL resource property
            // This will allow the 3rd party editors to look at this property 
            // and change to RTL for controls that support RTL.
            // We set the resource to the primary selections RTL property. 
            FlowDirection commmonFD = FlowDirection.LeftToRight; 
            if (_lastNotifiedSelection != null && _lastNotifiedSelection.PrimarySelection != null)
            { 

                FrameworkElement selectedElement = _lastNotifiedSelection.PrimarySelection.View as FrameworkElement;
                if (selectedElement != null)
                { 
                    commmonFD = selectedElement.FlowDirection;
                } 
 
                // In case of mulitislection,
                // if the FlowDirection is different then always set it to LTR. 
                // else set it to common FD.
                if (_lastNotifiedSelection.SelectionCount > 1)
                {
                    foreach (ModelItem item in _lastNotifiedSelection.SelectedObjects) 
                    {
                        FrameworkElement curElm = item.View as FrameworkElement; 
                        if (curElm != null && curElm.FlowDirection != commmonFD) 
                        {
                            //reset to LTR (since the FD's are different within multiselect) 
                            commmonFD = FlowDirection.LeftToRight;
                            break;
                        }
                    } 
                }
            } 
 
            PropertyInspectorResources.GetResources()["SelectedControlFlowDirectionRTL"] = commmonFD;
 
            RefreshPropertyList(false);

            UpdateSelectionPropertyChangedEventHooks(_displayedSelection, _lastNotifiedSelection);
            _displayedSelection = _lastNotifiedSelection; 
            _lastParent = GetCommonParent(_lastNotifiedSelection);
 
            // Handle dangling transactions 
            _defaultCommandHandler.CommitOpenTransactions();
 
            OnPropertyChanged("IsInfoBarNameReadOnly");
            OnPropertyChanged("SelectionName");
            OnPropertyChanged("SelectionIcon");
            OnPropertyChanged("SelectionTypeName"); 
        }
 
        // Removes / adds a PropertyChanged listener from / to the previous / current selection 
        private void UpdateSelectionPropertyChangedEventHooks(View.Selection previousSelection, View.Selection currentSelection)
        { 
            if (previousSelection != null && previousSelection.PrimarySelection != null)
            {
                previousSelection.PrimarySelection.PropertyChanged -= OnSelectedItemPropertyChanged;
            } 

            if (currentSelection != null && currentSelection.PrimarySelection != null) 
            { 
                currentSelection.PrimarySelection.PropertyChanged += OnSelectedItemPropertyChanged;
            } 
        }

        private void OnSelectedItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        { 
            if (_ignoreSelectionNameChanges)
            { 
                return; 
            }
 
            // PS 40699 - Name is not a special property for WF
            //if ("Name".Equals(e.PropertyName))
            //{
            //  OnSelectedItemNameChanged(); 
            //}
 
            if ("Parent".Equals(e.PropertyName)) 
            {
                OnParentChanged(); 
            }
        }

        // Called when the name changes 
        private void OnSelectedItemNameChanged()
        { 
            OnPropertyChanged("SelectionName"); 
        }
 
        // Called when the parent of the current selection changes
        private void OnParentChanged()
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new MethodInvoker(OnParentChangedIdle)); 
        }
 
        private void OnParentChangedIdle() 
        {
            if (_displayedSelection == null || _displayedSelection.SelectionCount < 1) 
            {
                return;
            }
 
            ModelItem newParent = GetCommonParent(_displayedSelection);
 
            if (_lastParent != newParent) 
            {
                RefreshPropertyList(true); 
                _lastParent = newParent;
            }
        }
 
        // Looks for common parent ModelItem among all the items in the selection
        private static ModelItem GetCommonParent(View.Selection selection) 
        { 
            if (selection == null || selection.SelectionCount < 1)
            { 
                return null;
            }

            ModelItem parent = null; 
            foreach (ModelItem item in selection.SelectedObjects)
            { 
                if (parent == null) 
                {
                    parent = item.Parent; 
                }
                else if (parent != item.Parent)
                {
                    return null; 
                }
            } 
 
            return parent;
        } 

        // The user can only specify the name for the selected objects iff exactly one
        // object is selected.
        private static bool CanSetSelectionName(View.Selection selection) 
        {
            return selection != null && selection.SelectionCount == 1; 
        } 

        private static bool AreSelectionsEquivalent(View.Selection a, View.Selection b) 
        {
            if (a == null && b == null)
            {
                return true; 
            }
            if (a == null || b == null) 
            { 
                return false;
            } 
            if (a.SelectionCount != b.SelectionCount)
            {
                return false;
            } 

            // POSSIBLE OPTIMIZATION: be smarter about same selection in a different order 
            IEnumerator ea = a.SelectedObjects.GetEnumerator(); 
            IEnumerator eb = b.SelectedObjects.GetEnumerator();
 
            while (ea.MoveNext() && eb.MoveNext())
            {
                if (!object.Equals(ea.Current, eb.Current))
                { 
                    return false;
                } 
            } 

            return true; 
        }

        // This is the work-horse that refreshes the list of properties and categories within a PropertyInspector
        // window, including refreshing of CategoryEditors, based on the specified selection 
        private void UpdateCategories(View.Selection selection, bool attachedOnly)
        { 
 
            // Optimization stolen from Sparkle:
            // re-rendering the categories is the number one perf issue. Clearing 
            // the databound collection results in massive Avalon code execution, and
            // then re-adding everything causes another huge shuffle. What is more,
            // even when changing the selection between different objects, most properties
            // do not change. Therefore we are going to take the new list of properties 
            // and we are going to merge them into the existing stuff, using an
            // approach I call Mark, Match, and Cull. 
            // 
            // First we mark all the properties in the current collection. Those which
            // are still marked at the end will be culled out 
            foreach (ModelCategoryEntry category in _categoryList)
            {
                if (attachedOnly)
                { 
                    category.MarkAttachedPropertiesDisassociated();
                } 
                else 
                {
                    category.MarkAllPropertiesDisassociated(); 
                }
            }

            // Second we try to match each property in the list of properties for the newly selected objects 
            // against something that we already have. If we have a match, then we reset the existing
            // ModelPropertyEntry and clear the mark 
            // 
            foreach (IEnumerable propertySet in
                ModelPropertyMerger.GetMergedProperties( 
                selection == null ? null : selection.SelectedObjects,
                selection == null ? 0 : selection.SelectionCount))
            {
 
                string propertyName = GetPropertyName(propertySet);
 
                // Specifically filter out the Name property 
                // PS 40699 - Name is not a special property for WF
                //if ("Name".Equals(propertyName)) 
                //{
                //    continue;
                //}
 
                if (attachedOnly && propertyName.IndexOf('.') < 0)
                { 
                    continue; 
                }
 
                ModelPropertyEntry wrappedProperty = _propertyToolBar.CurrentViewManager.AddProperty(propertySet, propertyName, _categoryList);

                // Make sure no valid properties get culled out
                wrappedProperty.Disassociated = false; 
            }
 
            // Third, we walk the properties and categories, and we cull out all of the 
            // marked properties. Empty categories are removed.
            // 
            for (int i = _categoryList.Count - 1; i >= 0; i--)
            {
                ModelCategoryEntry category = (ModelCategoryEntry)_categoryList[i];
                category.CullDisassociatedProperties(); 
                if (category.IsEmpty)
                { 
                    _categoryList.RemoveAt(i); 
                }
            } 

            _categoryList.RefreshFilter();
        }
 
        // Helper method that adjusts the visible set of CategoryEditors based on the specified selection
        private void UpdateCategoryEditors(View.Selection selection) 
        { 

            // Figure out which category editors to show 
            Dictionary newCategoryEditorTypes = _propertyToolBar.CurrentViewManager.GetCategoryEditors(
                FindCommonType(selection == null ? null : selection.SelectedObjects),
                _categoryList);
 
            // Figure out which CategoryEditors are no longer needed and remove them
            List editorTypesToRemove = null; 
            foreach (KeyValuePair item in _activeCategoryEditors) 
            {
                if (!newCategoryEditorTypes.ContainsKey(item.Key) || !IsCategoryShown(item.Key)) 
                {

                    // New selection does not include this existing category editor
                    // or the category that contains this editor 
                    // so remove the editor.
                    if (editorTypesToRemove == null) 
                    { 
                        editorTypesToRemove = new List();
                    } 

                    editorTypesToRemove.Add(item.Key);
                }
                else 
                {
                    // This category editor already exists, so don't re-add it 
                    newCategoryEditorTypes.Remove(item.Key); 
                }
            } 

            if (editorTypesToRemove != null)
            {
                foreach (Type editorTypeToRemove in editorTypesToRemove) 
                {
                    ModelCategoryEntry affectedCategory = _categoryList.FindCategory(_activeCategoryEditors[editorTypeToRemove]) as ModelCategoryEntry; 
                    if (affectedCategory != null) 
                    {
                        affectedCategory.RemoveCategoryEditor(editorTypeToRemove); 
                    }

                    _activeCategoryEditors.Remove(editorTypeToRemove);
                } 
            }
 
            // Figure out which CategoryEditors are now required and add them 
            foreach (Type editorTypeToAdd in newCategoryEditorTypes.Keys)
            { 
                CategoryEditor editor = (CategoryEditor)ExtensibilityAccessor.SafeCreateInstance(editorTypeToAdd);
                if (editor == null)
                {
                    continue; 
                }
 
                ModelCategoryEntry affectedCategory = _categoryList.FindCategory(editor.TargetCategory) as ModelCategoryEntry; 
                if (affectedCategory == null)
                { 
                    continue;
                }

                affectedCategory.AddCategoryEditor(editor); 
                _activeCategoryEditors[editorTypeToAdd] = editor.TargetCategory;
            } 
        } 

        // Check if the category is shown for the current category editor type 
        private bool IsCategoryShown(Type categoryEditorType)
        {
            bool ret = true;
            CategoryEditor editorToRemove = (CategoryEditor)ExtensibilityAccessor.SafeCreateInstance(categoryEditorType); 
            if (editorToRemove != null)
            { 
                ModelCategoryEntry affectedCategory = _categoryList.FindCategory(editorToRemove.TargetCategory) as ModelCategoryEntry; 
                if (affectedCategory == null)
                { 
                    ret = false;
                }
            }
            else 
            {
                ret = false; 
            } 
            return ret;
        } 

        // Tries to figure out what property to select and selects is
        private void UpdateSelectedProperty(View.Selection selection)
        { 

            // If we are not loaded, skip any and all selection magic 
            if (!this.IsLoaded) 
            {
                return; 
            }

            if (selection != null)
            { 

                // See what the view would like us to select if we run out of things 
                // we can think of selecting 
                //
                SelectionPath fallbackSelection = null; 
                if (_propertyToolBar.CurrentViewManager != null)
                {
                    fallbackSelection = _propertyToolBar.CurrentViewManager.GetDefaultSelectionPath(_categoryList);
                } 

                // Select the first thing we request that exists, using the following 
                // precedence order: 
                //
                //  * LastSelectionPath 
                //  * DefaultProperty
                //  * Whatever the view wants to show (first category, first property, ...)
                //
                _categoryList.UpdateSelectedProperty( 
                    this.LastSelectionPath,
                    ModelPropertyMerger.GetMergedDefaultProperty(selection.SelectedObjects), 
                    fallbackSelection); 
            }
        } 

        private static Type FindCommonType(IEnumerable modelItems)
        {
            Type commonType = null; 

            if (modelItems != null) 
            { 
                foreach (ModelItem selectedItem in modelItems)
                { 
                    if (commonType == null)
                    {
                        commonType = selectedItem.ItemType;
                    } 
                    else
                    { 
                        commonType = ModelUtilities.GetCommonAncestor(commonType, selectedItem.ItemType); 
                    }
                } 
            }

            return commonType;
        } 

        private static bool AreHomogenous(IEnumerable items) 
        { 
            Fx.Assert(items != null, "items parameter is null");
 
            Type type = null;
            foreach (ModelItem item in items)
            {
                if (type == null) 
                {
                    type = item.ItemType; 
                } 
                else if (type != item.ItemType)
                { 
                    return false;
                }
            }
 
            return true;
        } 
 
        // Static Helpers
 
        private static string GetPropertyName(IEnumerable propertySet)
        {
            if (propertySet == null)
            { 
                return null;
            } 
            foreach (ModelProperty property in propertySet) 
            {
                return property.Name; 
            }
            return null;
        }
 
        private static Image GetEmbeddedImage(string imageName)
        { 
            Image image = new Image(); 
            image.Source = new BitmapImage(new Uri(
                string.Concat( 
                "/System.Activities.Presentation;component/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Resources/",
                imageName),
                UriKind.RelativeOrAbsolute));
            return image; 
        }
 
 
        // AutomationPeer Stuff
 
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new PropertyInspectorAutomationPeer(this);
        } 

 
        // Cross-domain State Storage 

        //  
        // Clears the FilterString
        // 
        public void ClearFilterString()
        { 
            _categoryList.FilterString = null;
        } 
 
        // INotifyPropertyChanged Members
 
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            { 
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            } 
        } 

        private delegate void MethodInvoker(); 
        private delegate void UpdateSelectedPropertyInvoker(View.Selection selection);

        // Container for property-selection state represented by SelectionPath.
        // Since we receive a stored SelectionPath on the reload of this control, 
        // at which point the visuals themselves have not been rendered yet, we
        // store the supplied SelectionPath instance and use it to select the 
        // correct property only after the UI has been rendered. 
        //
        private class SelectionPathStateContainer : IStateContainer 
        {
            private PropertyInspector _parent;

            public SelectionPathStateContainer(PropertyInspector parent) 
            {
                if (parent == null) 
                { 
                    throw FxTrace.Exception.ArgumentNull("parent");
                } 
                _parent = parent;
            }

            // 
            // Pulls the SelectionPath from the CategoryList, but only if it was Sticky,
            // meaning we should preserve it 
            // 
            public object RetrieveState()
            { 
                if (_parent.CategoryList != null)
                {
                    SelectionPath path = _parent._objectSelectionInitialized ? _parent.CategoryList.SelectionPath : _parent.LastSelectionPath;
                    return path == null ? null : path.State; 
                }
 
                return null; 
            }
 
            //
            // Pulls the SelectionPath from the CategoryList, but only if it was Sticky,
            // meaning we should preserve it
            // 
            public void RestoreState(object state)
            { 
                if (state != null) 
                {
                    SelectionPath restoredPath = SelectionPath.FromState(state); 
                    _parent.LastSelectionPath = restoredPath;
                }
            }
        } 
    }
} 

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

10809,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelUtilities.cs/1305376/ModelUtilities.cs,4/26/2010 8:54:39 AM,9327
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections.Generic; 
    using System.Diagnostics.CodeAnalysis; 
    using System.Text;
    using System.Windows.Markup; 
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.PropertyEditing;

    //  
    // Static class full of useful helpers
    //  
    internal static class ModelUtilities 
    {
 
        // 
        // Compares the name and Type of the specified ModelProperties,
        // returning true if they are equal.
        //  
        // ModelProperty A
        // ModelProperty B 
        // True if the names and Types of the specified ModelProperties 
        // match, false otherwise.
        public static bool AreEquivalent(ModelProperty a, ModelProperty b) 
        {
            return object.Equals(a.Name, b.Name) &&
                object.Equals(a.PropertyType, b.PropertyType);
        } 

        //  
        // Gets the underlying value object of the specified ModelProperty.  MarkupExtensions 
        // (resources and such) will be returned as they are, with the exception of NullExtension,
        // which will be returned as null. 
        // 
        // ModelProperty to ---- open (can be null)
        // Underlying value object, if any
        public static object GetSafeRawValue(ModelProperty property) 
        {
            return GetSafeValue(property, false); 
        } 

        //  
        // Gets the underlying computed value object of the specified ModelProperty.  MarkupExtensions
        // (resources and such) will be resolved into their final value.
        // 
        // ModelProperty to ---- open (can be null) 
        // Underlying value object, if any
        public static object GetSafeComputedValue(ModelProperty property) 
        { 
            return GetSafeValue(property, true);
        } 

        private static object GetSafeValue(ModelProperty property, bool resolveReferences)
        {
            if (property == null) 
            {
                return null; 
            } 

            object value; 

            // We have to special case TextBlock due to IAddChild behavior with Text and Inlines
            if (resolveReferences && !(typeof(System.Windows.Controls.TextBlock).IsAssignableFrom(property.Parent.ItemType) &&
                property.Name.Equals(System.Windows.Controls.TextBlock.TextProperty.Name))) 
            {
                value = property.ComputedValue; 
            } 
            else
            { 
                value = property.Value == null ? null : property.Value.GetCurrentValue();
            }

            if (value == null || value.GetType().Equals(typeof(NullExtension))) 
            {
                return null; 
            } 

            return value; 
        }

        // 
        // Looks for the x:Name or Name property of the given PropertyValue and returns it if found. 
        // Note: this method is expensive because it evaluates all the sub-properties of the given
        // PropertyValue. 
        //  
        // PropertyValue instance to look at
        // Name if the PropertyValue defines one, null otherwise 
        public static string GetPropertyName(PropertyValue propertyValue)
        {
            if (propertyValue == null)
            { 
                return null;
            } 
 
            if (propertyValue.HasSubProperties)
            { 
                PropertyEntry nameProperty = propertyValue.SubProperties["Name"];
                if (nameProperty != null)
                {
                    return nameProperty.PropertyValue.StringValue; 
                }
            } 
 
            return null;
        } 

        // 
        // Returns ',' separated property name for sub-properties, going all the way
        // to the root ancestor in the property editing OM.  (ie. you get strings 
        // such as 'ContextMenu,IsEnabled' instead of just 'IsEnabled'.
        //  
        // Property to get the name of 
        // ',' separated property name for sub-properties
        public static string GetSubPropertyHierarchyPath(PropertyEntry property) 
        {
            if (property == null)
            {
                return null; 
            }
 
            if (property.ParentValue == null) 
            {
                return property.PropertyName; 
            }

            StringBuilder sb = new StringBuilder();
            do 
            {
                if (sb.Length > 0) 
                { 
                    sb.Insert(0, ',');
                } 

                sb.Insert(0, property.PropertyName);
                property = property.ParentValue == null ? null : property.ParentValue.ParentProperty;
 
            } while (property != null && !(property is ModelPropertyIndexer));
 
            return sb.ToString(); 
        }
 
        // 
        // Same as GetSubPropertyHierarchyPath(), but it looks up a cached version
        // of this path, if one exists, or calculates one from scratch and caches it
        // if it doesn't. 
        // 
        // Property to get the name of 
        // ',' separated property name for sub-properties 
        public static string GetCachedSubPropertyHierarchyPath(PropertyEntry property)
        { 
            ModelPropertyEntry mpe = property as ModelPropertyEntry;
            return mpe == null ? GetSubPropertyHierarchyPath(property) : mpe.SubPropertyHierarchyPath;
        }
 
        // 
        // Determines whether the specified type is implement generic Ilist interface. 
        //  
        // The type.
        //  
        // 	true if the specified type is implement generic Ilist interface;otherwise, false.
        // 
        public static bool ImplementsIList(Type type)
        { 
            bool ret = false;
            if (!type.IsGenericType) 
            { 
                ret = false;
            } 
            Type[] interfaceTypes = type.GetInterfaces();
            foreach (Type interfaceType in interfaceTypes)
            {
                if (interfaceType.IsGenericType && 
                    interfaceType.GetGenericTypeDefinition() == typeof(IList < > ))
                { 
                    ret = true; 
                    break;
                } 
            }
            return ret;
        }
 
        // 
        // Determines whether the specified type is implement generic ICollection interface. 
        //  
        // The type.
        //  
        // 	true if the specified type is implement generic ICollection interface;otherwise, false.
        // 
        public static bool ImplementsICollection(Type type)
        { 
            bool ret = false;
            if (!type.IsGenericType) 
            { 
                ret = false;
            } 
            Type[] interfaceTypes = type.GetInterfaces();
            foreach (Type interfaceType in interfaceTypes)
            {
                if (interfaceType.IsGenericType && 
                    interfaceType.GetGenericTypeDefinition() == typeof(ICollection < > ))
                { 
                    ret = true; 
                    break;
                } 
            }
            return ret;
        }
 
        // 
        // Tries to determine the common type ancestor of the specified types 
        //  
        // Type 1
        // Type 2 
        // Common ancestor Type, if any
        public static Type GetCommonAncestor(Type t1, Type t2)
        {
            if (t1 == null || t2 == null) 
            {
                return null; 
            } 

            if (t1 == typeof(object) || t2 == typeof(object)) 
            {
                return typeof(object);
            }
 
            if (t1.IsAssignableFrom(t2))
            { 
                return t1; 
            }
 
            while (t2 != typeof(object))
            {
                if (t2.IsAssignableFrom(t1))
                { 
                    return t2;
                } 
 
                t2 = t2.BaseType;
            } 

            return typeof(object);
        }
    } 
}

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

10810,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelPropertyValue.cs/1305376/ModelPropertyValue.cs,4/26/2010 8:54:39 AM,15473
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Data; 
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Windows; 
    using System.Windows.Input;
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Text;
 
    using System.Activities.Presentation;
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.PropertyEditing;
 
    using System.Activities.Presentation.Internal.PropertyEditing.Resources;
    using System.Activities.Presentation.Internal.Properties; 
    using System.Activities.Presentation.Internal.PropertyEditing.Editors; 

    //  
    // Concrete implementation of PropertyValue that delegates to ModelPropertyEntryBase for
    // all actions.
    // 
    internal class ModelPropertyValue : PropertyValue 
    {
 
        // Object used to mark a property value that should be cleared instead of set 
        private static readonly object ClearValueMarker = new object();
 
        // CultureInfo instance we use for formatting values so that they reflect what is in Xaml
        private static CultureInfo _xamlCultureInfo;

        //  
        // Basic ctor
        //  
        // Parent ModelPropertyEntryBase 
        public ModelPropertyValue(ModelPropertyEntryBase parentProperty) : base(parentProperty)
        { 
        }

        // 
        // Returns the source of this property value 
        // 
        public override PropertyValueSource Source 
        { 
            get {
                return ParentModelPropertyEntry.Source; 
            }
        }

        //  
        // Returns true if this value represents the default value of the property
        //  
        public override bool IsDefaultValue 
        {
            get { 
                return Source == DependencyPropertyValueSource.DefaultValue;
            }
        }
 
        // 
        // Returns true if the value contained by this property is mixed 
        //  
        public override bool IsMixedValue
        { 
            get {
                return ParentModelPropertyEntry.IsMixedValue;
            }
        } 

        //  
        // Returns true if custom TypeConverter exists and if it can convert 
        // the value from string.
        //  
        public override bool CanConvertFromString
        {
            get {
                return ParentModelPropertyEntry.Converter != null && 
                    ParentModelPropertyEntry.Converter.CanConvertFrom(typeof(string));
            } 
        } 

        //  
        // Gets a flag indicating whether this PropertyValue has sub properties
        // 
        public override bool HasSubProperties
        { 
            get {
                return ParentModelPropertyEntry.HasSubProperties; 
            } 
        }
 
        // 
        // Gets the sub-properties of the PropertyValue
        // 
        public override PropertyEntryCollection SubProperties 
        {
            get { 
                return ParentModelPropertyEntry.SubProperties; 
            }
        } 

        // 
        // Gets a flag indicating whether this PropertyValue represents a collection
        //  
        public override bool IsCollection
        { 
            get { 
                return ParentModelPropertyEntry.IsCollection;
            } 
        }

        // 
        // Gets the collection represented by this PropertyValue 
        // 
        public override PropertyValueCollection Collection 
        { 
            get {
                return ParentModelPropertyEntry.Collection; 
            }
        }

        //  
        // This is an internal helper to which we can bind and on which we fire PropertyChanged
        // event when the Name sub-property (if one exists) changes.  More-specifically, 
        // we bind to this property in CollectionEditor to display the Type as well as the 
        // Name of the items in the collection.  This property is accessed from XAML.
        //  
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        public PropertyValue NameSensitiveInstance
        {
            get { 
                return this;
            } 
        } 

        //  
        // Always catch exceptions
        // 
        protected override bool CatchExceptions
        { 
            get {
                return true; 
            } 
        }
 
        // 
        // Gets an en-us CultureInfo that ignores user-specified settings
        // 
        private static CultureInfo XamlCultureInfo 
        {
            get { 
                if (_xamlCultureInfo == null) 
                {
                    _xamlCultureInfo = new CultureInfo("en-us", false); 
                }

                return _xamlCultureInfo;
            } 
        }
 
        // Convenience accessor 
        private ModelPropertyEntryBase ParentModelPropertyEntry
        { 
            get {
                return (ModelPropertyEntryBase)this.ParentProperty;
            }
        } 

        //  
        // Validates the value using the TypeConverter, if one exists 
        // 
        // Value to validate 
        protected override void ValidateValue(object valueToValidate)
        {
            // Noop.  We used to rely on TypeConverter.IsValid() here, but it turns out
            // that a bunch of standard TypeConverters don't really work (eg. Int32TypeConverter 
            // returns true for IsValid("abc") and EnumConverter returns false for
            // IsValid(MyEnum.One | MyEnum.Two) even if MyEnum if adorned with FlagsAttribute) 
        } 

        // Called when there exists a Name sub-property for this value and it changes 
        internal void OnNameSubPropertyChanged()
        {
            // Updates XAML bindings (collection editor item-display-name-template for one)
            this.OnPropertyChanged("NameSensitiveInstance"); 
        }
 
        //  
        // Convert the specified string to a value
        //  
        // 
        // 
        protected override object ConvertStringToValue(string stringToConvert)
        { 
            if (this.ParentProperty.PropertyType == typeof(string))
            { 
                return stringToConvert; 
            }
            else if (string.IsNullOrEmpty(stringToConvert)) 
            {

                // If the type of this property is string:
                // 
                //      StringValue of ''   -> set Value to ''
                //      StringValue of null -> ClearValue() 
                // 
                // Otherwise
                // 
                //      StringValue of ''   -> ClearValue()
                //      StringValue of null -> ClearValue()
                //
                if (stringToConvert != null && typeof(string).Equals(this.ParentProperty.PropertyType)) 
                {
                    return null; 
                } 
                else
                { 
                    return ClearValueMarker;
                }

            } 
            else if (EditorUtilities.IsNullableEnumType(this.ParentProperty.PropertyType) && stringToConvert.Equals(EditorUtilities.NullString, StringComparison.Ordinal))
            { 
                // PS 107537: Special case handling when converting a string to a nullable enum type. 
                return null;
            } 
            else if (this.ParentModelPropertyEntry.Converter != null &&
                this.ParentModelPropertyEntry.Converter.CanConvertFrom(typeof(string)))
            {
 
                return this.ParentModelPropertyEntry.Converter.ConvertFromString(null, XamlCultureInfo, stringToConvert);
            } 
 
            throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(
                CultureInfo.CurrentCulture, 
                Resources.PropertyEditing_NoStringToValueConversion,
                this.ParentProperty.DisplayName)));
        }
 
        // 
        // Convert the specified value to a string 
        //  
        // 
        //  
        protected override string ConvertValueToString(object valueToConvert)
        {
            string stringValue = string.Empty;
 
            if (valueToConvert == null)
            { 
                if (typeof(IList).IsAssignableFrom(this.ParentProperty.PropertyType)) 
                {
                    stringValue = Resources.PropertyEditing_DefaultCollectionStringValue; 
                }
                else if (EditorUtilities.IsNullableEnumType(this.ParentProperty.PropertyType))
                {
                    // PS 107537: Special case handling when converting a nullable enum type to a string. 
                    return EditorUtilities.NullString;
                } 
                return stringValue; 
            }
            else if ((stringValue = valueToConvert as string) != null) 
            {
                return stringValue;
            }
 
            TypeConverter typeConverter = this.ParentModelPropertyEntry.Converter;
            if (valueToConvert is Array) 
            { 
                stringValue = Resources.PropertyEditing_DefaultArrayStringValue;
            } 
            else if (valueToConvert is IList
                || valueToConvert is ICollection
                || ModelUtilities.ImplementsICollection(valueToConvert.GetType())
                || ModelUtilities.ImplementsIList(valueToConvert.GetType())) 
            {
                stringValue = Resources.PropertyEditing_DefaultCollectionStringValue; 
            } 
            else if (valueToConvert is IEnumerable)
            { 
                stringValue = Resources.PropertyEditing_DefaultEnumerableStringValue;
            }
            else if (typeConverter != null && typeConverter.CanConvertTo(typeof(string)))
            { 
                stringValue = typeConverter.ConvertToString(null, XamlCultureInfo, valueToConvert);
            } 
            else 
            {
                stringValue = valueToConvert.ToString(); 
            }

            return stringValue ?? string.Empty;
        } 

 
        //  
        // Redirect the call to parent PropertyEntry
        //  
        // 
        protected override object GetValueCore()
        {
            return ParentModelPropertyEntry.GetValueCore(); 
        }
 
        //  
        // Redirect the call to parent PropertyEntry
        //  
        // 
        protected override void SetValueCore(object value)
        {
            if (value == ClearValueMarker) 
            {
                ParentModelPropertyEntry.ClearValue(); 
            } 
            else
            { 
                ParentModelPropertyEntry.SetValueCore(value);
            }
        }
 
        // 
        // Apply the FlowDirection to the resource. 
        //  
        private void CheckAndSetFlowDirectionResource()
        { 
            // Check if the value being edited is FlowDirection
            // and if so, reset the resource to the current value that the user is setting.
            // This will refresh the property inspector and all the string editors, showing "string" properties,
            // would have their FlowDirection set to the current value. 
            if (ParentModelPropertyEntry.PropertyName.Equals(FrameworkElement.FlowDirectionProperty.Name))
            { 
                object value = Value; 
                if (value != null)
                { 
                    PropertyInspectorResources.GetResources()["SelectedControlFlowDirectionRTL"] = value;
                }
            }
        } 

        //  
        // Redirect the call to parent PropertyEntry 
        // 
        public override void ClearValue() 
        {
            ParentModelPropertyEntry.ClearValue();
        }
 
        // 
        // Fires the appropriate PropertyChanged events 
        //  
        public void OnUnderlyingModelChanged()
        { 
            CheckAndSetFlowDirectionResource();
            this.NotifyRootValueChanged();
        }
 
        // 
        // Fires the appropriate PropertyChanged events 
        //  
        public void OnUnderlyingSubModelChanged()
        { 
            this.NotifySubPropertyChanged();
        }

        //  
        // Called when there is an error setting or getting a PropertyValue.
        // Displays an error dialog. 
        //  
        // 
        protected override void OnPropertyValueException(PropertyValueExceptionEventArgs e) 
        {
            if (e.Source == PropertyValueExceptionSource.Set)
            {
                if (e.Exception != null) 
                {
                    Debug.WriteLine(e.Exception.ToString()); 
                } 

                ErrorReporting.ShowErrorMessage(e.Exception.Message); 

                base.OnPropertyValueException(e);
            }
            else 
            {
                base.OnPropertyValueException(e); 
            } 
        }
 
        // 
        // Debuging-friendly ToString()
        // 
        //  
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public override string ToString() 
        { 
            try
            { 
                string value;
                if (this.Value == null)
                {
                    value = "{null}"; 
                }
                else 
                { 
                    value = this.StringValue;
                    if (string.IsNullOrEmpty(value)) 
                    {
                        value = "{empty}";
                    }
                } 

                return string.Format(CultureInfo.CurrentCulture, "{0} (PropertyValue)", value ?? "{null}"); 
            } 
            catch
            { 
                return base.ToString();
            }
        }
    } 
}

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

10811,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelPropertyMerger.cs/1305376/ModelPropertyMerger.cs,4/26/2010 8:54:39 AM,11544
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Diagnostics.CodeAnalysis; 
    using System.Text;
    using System.Activities.Presentation.Model;

    //  
    // Helper class that knows how to merge ModelProperties across multiple ModelItems
    //  
    internal static class ModelPropertyMerger 
    {
 
        private static IEnumerable> _emptyCollection;

        private static IEnumerable> EmptyCollection
        { 
            get {
                if (_emptyCollection == null) 
                { 
                    _emptyCollection = new List>();
                } 

                return _emptyCollection;
            }
        } 

        //  
        // Uber method that returns a list of list of ModelProperties that represent the 
        // merged set of properties across the specified ModelItems
        //  
        // ModelItems to examine
        // Count on ModelItems to examine
        // List of list of merged properties
        public static IEnumerable> GetMergedProperties(IEnumerable items, int itemCount) 
        {
            return GetMergedPropertiesHelper(new ModelItemExpander(items, itemCount)); 
        } 

        //  
        // Uber method that returns a list of list of ModelProperties that represent the
        // merged set of sub-properties across the values of the specified parent properties
        // 
        // ModelProperties to examine 
        // List of list of merged properties
        public static IEnumerable> GetMergedSubProperties(ICollection parentProperties) 
        { 
            return GetMergedPropertiesHelper(new SubPropertyExpander(parentProperties));
        } 

        // 
        // Finds the consolidated default property name and returns it.  If there is no shared
        // default property betweem the specified items, null is returned. 
        // 
        // Items to examine 
        // Shared default property, if any. 
        public static string GetMergedDefaultProperty(IEnumerable items)
        { 
            if (items == null)
            {
                return null;
            } 

            bool firstIteration = true; 
            string mergedDefaultProperty = null; 

            foreach (ModelItem item in items) 
            {
                string currentDefaultProperty = ExtensibilityAccessor.GetDefaultProperty(item.ItemType);

                if (firstIteration) 
                {
                    mergedDefaultProperty = currentDefaultProperty; 
                } 
                else if (!string.Equals(currentDefaultProperty, mergedDefaultProperty))
                { 
                    mergedDefaultProperty = null;
                }

                if (string.IsNullOrEmpty(mergedDefaultProperty)) 
                {
                    return null; 
                } 

                firstIteration = false; 
            }

            return mergedDefaultProperty;
        } 

        // Optimization that speeds up the common case (single selection) 
        private static IEnumerable> GetMergedPropertiesHelper(PropertyExpander expander) 
        {
            // Check empty list 
            if (expander == null || expander.ContainerCount == 0)
            {
                return EmptyCollection;
            } 

            if (expander.ContainerCount == 1) 
            { 
                // Corner case - one object selected, don't bother with merging
                return GetFirstProperties(expander); 
            }
            else
            {
                // Calculate the list anew 
                return GetMergedPropertiesCore(expander);
            } 
        } 

        // Optimization that speeds up the common case (single selection) 
        private static IEnumerable> GetFirstProperties(PropertyExpander expander)
        {
            IEnumerator> propertyContainers = expander.GetEnumerator();
            propertyContainers.MoveNext(); 

            if (propertyContainers.Current != null) 
            { 
                foreach (ModelProperty property in propertyContainers.Current)
                { 
                    yield return new ModelProperty[] { property };
                }
            }
        } 

        private static IEnumerable> GetMergedPropertiesCore(PropertyExpander expander) 
        { 

            Dictionary> counter = new Dictionary>(); 

            int containerCounter = 0;
            foreach (IEnumerable properties in expander)
            { 

                if (properties == null) 
                { 
                    yield break;
                } 

                foreach (ModelProperty property in properties)
                {
 
                    IList existingModelPropertiesForProperty;
                    if (!counter.TryGetValue(property.Name, out existingModelPropertiesForProperty)) 
                    { 

                        if (containerCounter == 0) 
                        {
                            existingModelPropertiesForProperty = new List(expander.ContainerCount);
                            counter[property.Name] = existingModelPropertiesForProperty;
                        } 
                        else
                        { 
                            // This property has not been encountered yet in the previous objects, 
                            // so skip it altogether.
                            continue; 
                        }

                    }
 
                    if (existingModelPropertiesForProperty.Count < containerCounter)
                    { 
                        // There has been a ModelItem in the list that didn't have this property, 
                        // so delete any record of it and skip it in the future.
                        counter.Remove(property.Name); 
                        continue;
                    }

                    // Verify that the properties are equivalent 
                    if (containerCounter > 0 &&
                        !ModelUtilities.AreEquivalent( 
                        existingModelPropertiesForProperty[containerCounter - 1], property)) { 
                        // They are not, so scrap this property altogether
                        counter.Remove(property.Name); 
                        continue;
                    }

                    existingModelPropertiesForProperty.Add(property); 
                }
 
                containerCounter++; 
            }
 
            foreach (KeyValuePair> pair in counter)
            {
                // Once again, if there is a property that is not shared by all
                // selected items, ignore it 
                if (pair.Value.Count < containerCounter)
                { 
                    continue; 
                }
 
                // We should not set the same instance to multiple properties,
                // so ignore types that are not value type or string in case of multi-selection
                if(pair.Value.Count > 1 && !(pair.Value[0].PropertyType.IsValueType || pair.Value[0].PropertyType.Equals(typeof(string))))
                { 
                    continue;
                } 
 
                yield return (IList)pair.Value;
            } 
        }

        // 
        // We use the same code to merge properties across a set of ModelItems as well 
        // as to merge sub-properties across a set of ModelProperties.  PropertyExpander
        // class is a helper that abstracts the difference between these two inputs, so 
        // that the merge methods don't have to worry about it. 
        // 
        private abstract class PropertyExpander : IEnumerable> 
        {
            public abstract int ContainerCount
            { get; }
            public abstract IEnumerator> GetEnumerator(); 

            IEnumerator IEnumerable.GetEnumerator() 
            { 
                return GetEnumerator();
            } 
        }

        // 
        // Version of PropertyExpander that returns the properties of a set of ModelItems 
        // 
        private class ModelItemExpander : PropertyExpander 
        { 

            private IEnumerable _items; 
            private int _itemCount;

            public ModelItemExpander(IEnumerable items, int itemCount)
            { 
                _items = items;
                _itemCount = itemCount; 
            } 

            public override int ContainerCount 
            {
                get { return _itemCount; }
            }
 
            public override IEnumerator> GetEnumerator()
            { 
                if (_items == null) 
                {
                    yield break; 
                }

                foreach (ModelItem item in _items)
                { 
                    if (item.Properties == null)
                    { 
                        continue; 
                    }
 
                    yield return item.Properties;
                }
            }
        } 

        //  
        // Version of PropertyExpander that returns the sub-properties of a set of 
        // ModelProperty values.
        //  
        private class SubPropertyExpander : PropertyExpander
        {

            private ICollection _parentProperties; 

            public SubPropertyExpander(ICollection parentProperties) 
            { 
                _parentProperties = parentProperties;
            } 

            public override int ContainerCount
            {
                get { return _parentProperties == null ? 0 : _parentProperties.Count; } 
            }
 
            public override IEnumerator> GetEnumerator() 
            {
                if (_parentProperties == null) 
                {
                    yield break;
                }
 
                foreach (ModelProperty property in _parentProperties)
                { 
                    yield return ExtensibilityAccessor.GetSubProperties(property); 
                }
            } 
        }
    }
}

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

10812,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelPropertyIndexer.cs/1305376/ModelPropertyIndexer.cs,4/26/2010 8:54:39 AM,12649
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Text;

    using System.Activities.Presentation; 
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.PropertyEditing; 
 
    using System.Activities.Presentation.Internal.Properties;
 
    // 
    // ModelPropertyIndexer is used to represent ModelItems in a collection.  As such
    // and unlike ModelProperty, the class wraps around a single ModelItem instead of
    // one or more ModelProperties. 
    // 
    internal class ModelPropertyIndexer : ModelPropertyEntryBase 
    { 

        private static readonly ICollection EmptyCollection = new object[0]; 

        private ModelItem _modelItem;
        private int _index;
        private ModelPropertyValueCollection _parentCollection; 

        private CachedValues _valueCache; 
 
        // 
        // Basic ctor.  Note, however, that this class should only be created by ModelPropertyValueCollection 
        // as that class ensures that the new instance is correctly added and removed from the
        // ModelItemMap.
        // 
        // ModelItem to wrap around 
        // Index of the ModelItem in the collection
        // Parent collection 
        public ModelPropertyIndexer( 
            ModelItem modelItem,
            int index, 
            ModelPropertyValueCollection parentCollection)
            : base(parentCollection.ParentValue)
        {
 
            if (modelItem == null)
            { 
                throw FxTrace.Exception.ArgumentNull("modelItem"); 
            }
            if (parentCollection == null) 
            {
                throw FxTrace.Exception.ArgumentNull("parentCollection");
            }
 
            _modelItem = modelItem;
            _index = index; 
            _parentCollection = parentCollection; 
            _valueCache = new CachedValues(this);
        } 


        // 
        // Gets the index of the underlying ModelItem.  If index < 0, this 
        // ModelPropertyIndexer no longer belongs to a collection and setting its value
        // will fail. 
        //  
        public int Index
        { 
            get {
                return _index;
            }
            internal set { 
                _index = value;
            } 
        } 

        //  
        // Gets the name category name of the parent collection
        // 
        public override string CategoryName
        { 
            get {
                return _parentCollection.ParentValue.ParentProperty.CategoryName; 
            } 
        }
 
        // 
        // Gets the description of the parent collection
        // 
        public override string Description 
        {
            get { 
                return _parentCollection.ParentValue.ParentProperty.Description; 
            }
        } 

        // 
        // Gets the IsAdvanced flag of the parent collection
        //  
        public override bool IsAdvanced
        { 
            get { 
                return _parentCollection.ParentValue.ParentProperty.IsAdvanced;
            } 
        }

        // 
        // Returns true 
        // 
        public override bool IsReadOnly 
        { 
            get { return true; }
        } 

        // 
        // Gets the index of this item as string
        //  
        public override string PropertyName
        { 
            get { 
                return _index.ToString(CultureInfo.InvariantCulture);
            } 
        }

        // 
        // Gets the type of items in the parent collection 
        // 
        public override Type PropertyType 
        { 
            get {
                return _modelItem.ItemType; 
            }
        }

        //  
        // Returns null because there are no ValueEditors for values that belong to a collection
        //  
        public override PropertyValueEditor PropertyValueEditor 
        {
            get { 
                // There are no ValueEditors for items in a collection
                return null;
            }
        } 

        //  
        // Returns an empty collection - there are no StandardValues for items in a collection 
        // 
        public override ICollection StandardValues 
        {
            get {
                // There are no StandardValues for items in a collection
                return EmptyCollection; 
            }
        } 
 
        // 
        // Returns false - ModelPropertyIndexers always wrap around a single ModelItem 
        // 
        public override bool IsMixedValue
        {
            get { return false; } 
        }
 
        //  
        // Returns Local - this PropertyEntry always contains a collection item value which is local
        //  
        public override PropertyValueSource Source
        {
            get { return DependencyPropertyValueSource.Local; }
        } 

        //  
        // Gets the TypeConverter 
        // 
        public override TypeConverter Converter 
        {
            get {
                return _valueCache.Converter;
            } 
        }
 
        //  
        // Gets the Type of the contained ModelItem
        //  
        public override Type CommonValueType
        {
            get {
                return _modelItem.ItemType; 
            }
        } 
 
        // 
        // Gets the sub-properties of the underlying item 
        // 
        public override PropertyEntryCollection SubProperties
        {
            get { 
                return _valueCache.SubProperties;
            } 
        } 

        //  
        // Gets the collection of the underlying ModelItem
        // 
        public override PropertyValueCollection Collection
        { 
            get {
                return _valueCache.Collection; 
            } 
        }
 
        // 
        // Gets the depth of this property in the PI sub-property tree.
        // Since this class represents an item in the collection, it's depth
        // resets to -1 so that it's children start at depth 0 ( -1 + 1 = 0) again. 
        // 
        public override int Depth 
        { 
            get {
                return -1; 
            }
        }

 
        // 
        // Gets the underlying ModelItem 
        //  
        internal ModelItem ModelItem
        { 
            get {
                return _modelItem;
            }
        } 

        //  
        // Gets a flag indicating whether the underlying collection instance has already been 
        // initialized.  Optimization.
        //  
        internal override bool CollectionInstanceExists
        {
            get {
                return _valueCache.CollectionInstanceExists; 
            }
        } 
 
        // 
        // Creates a new ModelPropertyValue instance 
        // 
        // New ModelPropertyValue instance
        protected override PropertyValue CreatePropertyValueInstance()
        { 
            return new ModelPropertyValue(this);
        } 
 
        // 
        // Gets the actual object instance respresented by this class 
        // 
        // Actual object instance respresented by this class
        public override object GetValueCore()
        { 
            return _modelItem.GetCurrentValue();
        } 
 
        // 
        // Sets the value of the collection item at the same position as the 
        // ModelItem represented by this class.  Identical to removing the old
        // item and adding a new one
        // 
        // Value to set 
        public override void SetValueCore(object value)
        { 
            throw FxTrace.Exception.AsError(new InvalidOperationException(Resources.PropertyEditing_ErrorSetValueOnIndexer)); 
        }
 
        // 
        // Throws an exception -- invalid operation
        // 
        public override void ClearValue() 
        {
            throw FxTrace.Exception.AsError(new InvalidOperationException(Resources.PropertyEditing_ClearIndexer)); 
        } 

        //  
        // Opens a new ModelEditingScope with the specified description.
        // 
        // Change description (may be null).
        // New, opened ModelEditingScope with the specified description 
        internal override ModelEditingScope BeginEdit(string description)
        { 
            return description == null ? _modelItem.BeginEdit() : _modelItem.BeginEdit(description); 
        }
 
        // 
        // Called when one of the sub-properties exposed by this class changes
        // 
        protected override void OnUnderlyingSubModelChangedCore() 
        {
            // Do nothing.  There is nothing in CachedValues right now that would need to 
            // be refreshed as a result of one of our sub-properties changing value 
        }
 
        // Cached values that need to be nixed when the underlying ModelItem changes
        // (ie. someone calls SetValueCore()).  Pretty much everything in here is an "expensive"
        // calculation which requires us to evaluate some attributes associated with the given
        // property of set of properties, so we cache the return values and keep that cache 
        // in a single place so that it's easy to know what needs to be ----d when the underlying
        // ModelItem changes. 
        private class CachedValues 
        {
 
            private static readonly TypeConverter NoTypeConverter = new TypeConverter();

            private ModelPropertyIndexer _parent;
 
            private TypeConverter _converter;
            private ModelPropertyEntryCollection _subProperties; 
            private ModelPropertyValueCollection _collection; 

            public CachedValues(ModelPropertyIndexer indexer) 
            {
                _parent = indexer;
            }
 
            public TypeConverter Converter
            { 
                get { 
                    if (_converter == null)
                    { 
                        _converter = ExtensibilityAccessor.GetTypeConverter(_parent._modelItem);
                        _converter = _converter ?? NoTypeConverter;
                    }
 
                    return _converter == NoTypeConverter ? null : _converter;
                } 
            } 

            public ModelPropertyEntryCollection SubProperties 
            {
                get {
                    if (_subProperties == null)
                    { 
                        _subProperties = new ModelPropertyEntryCollection(_parent);
                    } 
 
                    return _subProperties;
                } 
            }

            public bool CollectionInstanceExists
            { 
                get {
                    return _collection != null; 
                } 
            }
 
            public ModelPropertyValueCollection Collection
            {
                get {
                    if (_collection == null) 
                    {
                        _collection = new ModelPropertyValueCollection(_parent.ModelPropertyValue); 
                    } 

                    return _collection; 
                }
            }
        }
    } 
}

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

10813,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelPropertyEntry.cs/1438166/ModelPropertyEntry.cs,4/26/2010 8:54:39 AM,54222
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Text;
    using System.Windows; 
    using System.Windows.Data;
    using System.Windows.Markup; 
    using System.Windows.Media; 

    using System.Activities.Presentation; 
    using System.Activities.Presentation.Model;
    using System.Activities.Presentation.PropertyEditing;
    using System.Activities.Presentation.Services;
 
    using System.Activities.Presentation.Internal.Properties;
    using System.Runtime; 
    using System.Activities.Presentation.Internal.PropertyEditing.Editors; 

    //  
    // ModelPropertyEntry is a wrapper around Cider's ModelProperty and that
    // exposes its functionality through the PropertyEntry object model.  It handles
    // all get / set / clear functionality.
    //  
    internal class ModelPropertyEntry : ModelPropertyEntryBase, IComparable
    { 
        private const string _textBlockInlinesPropertyName = "Inlines"; 

        // Property names for TextBlock properties that require special handling 
        private static string _textBlockTextPropertyName = System.Windows.Controls.TextBlock.TextProperty.Name;

        // Cached values that need to be nixed when the underlying ModelProperty changes
        // (ie. someone calls SetProperty()) 
        private CachedValues _valueCache;
 
        // List of ModelProperties that this instance wraps around.  It 
        // is guaranteed to contain at least one ModelProperty instance (single
        // selection scenario), but it may contain multiple ModelProperty instances 
        // (multi-select scenario)
        private List _properties = new List();

        // Flag indicating whether this instance points to something valid. 
        // Used both as a perf optimization from PropertyInspector.UpdateCategories()
        // as well as to disable the making of changes to ModelPropertyEntries 
        // when the underlying ModelProperties are no longer available. 
        private bool _disassociated;
 
        // Bool indicating whether this property is a wrapper around the Name property
        // (which we special case for display purposes)
        private bool _wrapsAroundNameProperty;
 
        // 
        // Basic ctor that wraps around a single ModelProperty 
        //  
        // ModelProperty to wrap around
        // Parent PropertyValue, if any 
        [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public ModelPropertyEntry(ModelProperty property, ModelPropertyValue parentValue)
            : base(parentValue)
        { 

            _valueCache = new CachedValues(this); 
            SetUnderlyingModelPropertyHelper(property, false); 
        }
 
        // 
        // Basic ctor that wraps around multiple ModelProperties in the
        // multi-select scenario.  The code assumes that the ModelProperties in
        // the set all represent the same property (eg. Background) across different 
        // ModelItems (eg. Button, Grid, and ComboBox).
        //  
        // Set of ModelProperties to wrap around 
        // Parent PropertyValue, if any
        [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] 
        public ModelPropertyEntry(IEnumerable propertySet, ModelPropertyValue parentValue)
            : base(parentValue)
        {
 
            _valueCache = new CachedValues(this);
            SetUnderlyingModelPropertyHelper(propertySet, false); 
        } 

 
        // 
        // Gets the name of the contained property
        // 
        public override string PropertyName 
        {
            get { 
                return _properties[0].Name; 
            }
        } 

        // 
        // Gets the display name of the contained property, if any.
        // Defaults to property name if none is found. 
        // 
        public override string DisplayName 
        { 
            get {
                return _valueCache.DisplayName; 
            }
        }

        //  
        // Gets the type of the contained property
        //  
        public override Type PropertyType 
        {
            get { 
                return _properties[0].PropertyType;
            }
        }
 
        // 
        // Gets the category name of the contained property 
        //  
        public override string CategoryName
        { 
            get {
                return _valueCache.CategoryName;
            }
        } 

        //  
        // Gets the description of the contained property 
        // 
        public override string Description 
        {
            get {
                return _valueCache.Description;
            } 
        }
 
        //  
        // Gets a flad indicating whether the property is read-only
        //  
        public override bool IsReadOnly
        {
            get {
                return _valueCache.IsReadOnly; 
            }
        } 
 
        // 
        // Gets a flag indicating whether the property is advanced 
        // 
        public override bool IsAdvanced
        {
            get { 
                return _valueCache.IsAdvanced;
            } 
        } 

        //  
        // Gets a flag indicating whether this property is browsable or not
        // (All properties are exposed through the object model.  It's up to the
        // UI to make the display / don't-display decision)
        //  
        public bool IsBrowsable
        { 
            get { 
                return _valueCache.IsBrowsable;
            } 
        }

        // 
        // Gets a collection of standard values that can be assigned to 
        // the property
        //  
        public override ICollection StandardValues 
        {
            get { 
                return _valueCache.StandardValues;
            }
        }
 
        // 
        // Gets a flag indicating whether the list of StandardValues is complete 
        // or whether the user can type a value that's different from the ones in the list 
        // Note: this property is referenced from XAML
        //  
        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        public bool StandardValuesExclusive
        {
            get { 
                return _valueCache.StandardValuesExclusive;
            } 
        } 

        //  
        // Gets the PropertyValueEditor for this property
        // 
        public override PropertyValueEditor PropertyValueEditor
        { 
            get {
                return _valueCache.PropertyValueEditor; 
            } 
        }
 
        // 
        // Gets the TypeConverted for the contained property
        // 
        public override TypeConverter Converter 
        {
            get { 
                return _valueCache.Converter; 
            }
        } 

        // 
        // Gets the value Type for all contained properties if it matches,
        // null otherwise 
        // 
        public override Type CommonValueType 
        { 
            get {
                return _valueCache.CommonValueType; 
            }
        }

        //  
        // Returns true if the contained ModelProperties don't
        // share the same value 
        //  
        public override bool IsMixedValue
        { 
            get {
                return _valueCache.IsMixedValue;
            }
        } 

        //  
        // Gets the source of the value contained by this property 
        // 
        public override PropertyValueSource Source 
        {
            get {
                return _valueCache.Source;
            } 
        }
 
        //  
        // Gets the sub-properties of the contained property
        //  
        public override PropertyEntryCollection SubProperties
        {
            get {
                return _valueCache.SubProperties; 
            }
        } 
 
        // 
        // Gets the collection of PropertyValues if this ModelProperty represents 
        // a collection
        // 
        public override PropertyValueCollection Collection
        { 
            get {
                return _valueCache.Collection; 
            } 
        }
 
        // 
        // Gets a flag indicating whether the collection instance has already
        // been instantiated (perf optimization)
        //  
        internal override bool CollectionInstanceExists
        { 
            get { 
                return _valueCache.CollectionInstanceExists;
            } 
        }

        // 
        // Gets the underlying collection of ModelProperties 
        // 
        internal ICollection ModelPropertySet 
        { 
            get {
                return _properties; 
            }
        }

        //  
        // Gets the first underlying ModelProperty for cases when
        // this class wraps around multiple 
        //  
        internal ModelProperty FirstModelProperty
        { 
            get {
                return _properties[0];
            }
        } 

        //  
        // Gets an order token for property ordering 
        // 
        internal PropertyOrder PropertyOrder 
        {
            get {
                return _valueCache.PropertyOrder;
            } 
        }
 
        //  
        // Gets or sets the disassociated flag
        //  
        internal bool Disassociated
        {
            get { return _disassociated; }
            set { _disassociated = value; } 
        }
 
        //  
        // Gets a flag indicating whether this instance represents an attached DP
        //  
        internal bool IsAttached
        {
            get {
                return _valueCache.IsAttached; 
            }
        } 
 
        // 
        // Gets a list of CategoryEditor types associated with this PropertyEntry 
        // 
        internal IEnumerable CategoryEditorTypes
        {
            get { 
                return _valueCache.CategoryEditorTypes;
            } 
        } 

 
        // 
        // Returns true if there are standard values for this property.
        // 
        protected override bool HasStandardValues 
        {
            get { return _valueCache.StandardValuesSupported; } 
        } 

        //  
        // Replaces the underlying ModelProperty/ies with the specified ModelProperties.
        // Fires the appropriate PropertyChanged events
        // 
        // Property set to wrap around 
        public void SetUnderlyingModelProperty(IEnumerable propertySet)
        { 
            SetUnderlyingModelPropertyHelper(propertySet, true); 
        }
 
        private void SetUnderlyingModelPropertyHelper(ModelProperty property, bool firePropertyValueChangedEvents)
        {
            if (property == null)
            { 
                throw FxTrace.Exception.ArgumentNull("property");
            } 
 
            // Store the value
            ClearUnderlyingModelProperties(); 
            AddUnderlyingModelProperty(property);

            // Clear any cached values
            RefreshCache(); 

            if (firePropertyValueChangedEvents) 
            { 
                // Update the PropertyValue (always, except when it doesn't exist yet (ctor time))
                this.ModelPropertyValue.OnUnderlyingModelChanged(); 
            }
        }

        private void SetUnderlyingModelPropertyHelper(IEnumerable propertySet, bool firePropertyValueChangedEvents) 
        {
            if (propertySet == null) 
            { 
                throw FxTrace.Exception.ArgumentNull("propertySet");
            } 

            // Attempt to store the values
            int count = 0;
            foreach (ModelProperty property in propertySet) 
            {
                if (property == null) 
                { 
                    continue;
                } 

                if (count == 0)
                {
                    ClearUnderlyingModelProperties(); 
                }
 
                AddUnderlyingModelProperty(property); 
                count++;
            } 

            // Throw if the underlying property set was invalid
            if (count == 0)
            { 
                throw FxTrace.Exception.AsError(new ArgumentException("Cannot set the underlying ModelProperty to an empty set."));
            } 
 
            // Clear any cached values
            RefreshCache(); 

            if (firePropertyValueChangedEvents)
            {
                // Update the PropertyValue (always, except when it doesn't exist yet (ctor time)) 
                this.ModelPropertyValue.OnUnderlyingModelChanged();
            } 
        } 

        // Adds the property to the internal collection list and hooks into its PropertyChanged event 
        private void AddUnderlyingModelProperty(ModelProperty property)
        {
            if (property == null)
            { 
                return;
            } 
 
            property.Parent.PropertyChanged += new PropertyChangedEventHandler(OnUnderlyingPropertyChanged);
            _properties.Add(property); 
            _wrapsAroundNameProperty = "Name".Equals(property.Name);
        }

        internal void Disconnect() 
        {
            foreach (ModelProperty property in _properties) 
            { 
                property.Parent.PropertyChanged -= new PropertyChangedEventHandler(OnUnderlyingPropertyChanged);
            } 
        }

        // Removes all properties from the internal collection and unhooks from their PropertyChanged events
        private void ClearUnderlyingModelProperties() 
        {
            foreach (ModelProperty property in _properties) 
            { 
                property.Parent.PropertyChanged -= new PropertyChangedEventHandler(OnUnderlyingPropertyChanged);
            } 

            _properties.Clear();
            _wrapsAroundNameProperty = false;
        } 

        // Event handler for PropertyChanged event.  Called whenever any of the underlying properties that 
        // this ModelPropertyEntry wraps around changes. 
        private void OnUnderlyingPropertyChanged(object sender, PropertyChangedEventArgs e)
        { 
            if (!this.PropertyName.Equals(e.PropertyName))
            {
                return;
            } 

            this.OnUnderlyingModelChanged(); 
 
            // If this property is a sub-property of some other property we know and care
            // about, notify the parents as well 
            PropertyValue parentValue = this.ParentValue;
            while (parentValue != null)
            {
                ModelPropertyEntryBase parentProperty = (ModelPropertyEntryBase)parentValue.ParentProperty; 
                parentProperty.OnUnderlyingSubModelChanged();
                parentValue = parentProperty.ParentValue; 
            } 
        }
 
        // 
        // Clear any cached values
        // 
        protected override void RefreshCache() 
        {
            base.RefreshCache(); 
            _valueCache.ClearAll(); 
        }
 
        // 
        // Gets the underlying value as an object instance.  Mixed values will
        // return null.
        //  
        // Underlying value contained by this property.
        public override object GetValueCore() 
        { 
            if (this.IsMixedValue)
            { 
                return null;
            }

            object retValue = ModelUtilities.GetSafeComputedValue(_properties[0]); 

            return retValue; 
        } 

        //  
        // Sets the value of the underlying property / ies.
        // 
        // Value to set
        public override void SetValueCore(object value) 
        {
            // If this ModelPropertyEntry instance is no longer hooked up into 
            // the underlying model, ignore calls to SetValueCore() 
            if (_disassociated)
            { 
                return;
            }

            bool textBlockTextHackNeeded = false; 
            List textBlockTextProperties = null;
            if (typeof(System.Windows.Controls.TextBlock).IsAssignableFrom(_properties[0].Parent.ItemType)) { 
                textBlockTextHackNeeded = true; 
            }
 
            // POSSIBLE OPTIMIZATION: remember which properties were altered.  When on Idle we
            // receive global property changed events, ignore the ones we know about
            using (ModelEditingScope group = _properties[0].Parent.BeginEdit(
                string.Format( 
                CultureInfo.CurrentCulture,
                Resources.PropertyEditing_UndoText, 
                this.DisplayName))) 
            {
 
                for (int i = 0; i < _properties.Count; i++)
                {
                    if (textBlockTextHackNeeded && _properties[i].Name.Equals(_textBlockTextPropertyName)) {
                        // We need to set Text after we clear inlines! 
                        if (textBlockTextProperties == null)
                        { 
                            textBlockTextProperties = new List(); 
                        }
                        textBlockTextProperties.Add(_properties[i]); 
                        continue;
                    }
                    _properties[i].SetValue(value);
                } 

                // TextBlock has very bad IAddChild behavior with two properties contributing and having different 
                // views into the content (Text and Inlines).  To simplify editing, we clear Inlines when Text is set 
                // which is what most users want anyways
                if (textBlockTextProperties != null) 
                {
                    foreach (ModelProperty textBlockTextProperty in textBlockTextProperties)
                    {
                        ModelProperty inlinesProperty = textBlockTextProperty.Parent.Properties[_textBlockInlinesPropertyName]; 
                        if (inlinesProperty != null && inlinesProperty.Collection != null)
                        { 
                            inlinesProperty.Collection.Clear(); 
                        }
                        textBlockTextProperty.SetValue(value); 
                    }
                }

                if (group != null) 
                {
                    group.Complete(); 
                } 
            }
 
            _valueCache.ClearValueRelatedCacheItems();
            NotifyParentOfNameChanged();
        }
 
        // 
        // Clears the underlying property / ies. 
        //  
        public override void ClearValue()
        { 

            // If this ModelPropertyEntry instance is no longer hooked up into
            // the underlying model, ignore calls to ClearValue()
            if (_disassociated) 
            {
                return; 
            } 

            // POSSIBLE OPTIMIZATION: remember which properties were altered.  When on Idle we 
            // receive global property changed events, ignore the ones we know about

            using (ModelEditingScope group = _properties[0].Parent.BeginEdit(
                string.Format( 
                CultureInfo.CurrentCulture,
                Resources.PropertyEditing_UndoText, 
                this.DisplayName))) 
            {
 
                for (int i = 0; i < _properties.Count; i++)
                {
                    _properties[i].ClearValue();
                } 

                group.Complete(); 
            } 

            _valueCache.ClearValueRelatedCacheItems(); 
            NotifyParentOfNameChanged();
        }

        // If this property happens to wrap around the "Name" property, give our parent 
        // (if one exists) a heads-up that the value has changed.  We use this mechanism
        // to update display names of items in a collection editor. 
        private void NotifyParentOfNameChanged() 
        {
            if (!_wrapsAroundNameProperty) 
            {
                return;
            }
 
            ModelPropertyValue parentValue = this.ParentValue as ModelPropertyValue;
            if (parentValue == null) 
            { 
                return;
            } 

            // This PropertyEntry is the Name sub-property of another PropertyValue,
            // so let our parent know that its name has changed.
            parentValue.OnNameSubPropertyChanged(); 
        }
 
        //  
        // Called when the underlying ModelProperty changes.  Clears any cached
        // values and fires the appropriate changed events. 
        // 
        internal void OnUnderlyingModelChanged()
        {
            _valueCache.ClearValueRelatedCacheItems(); 
            this.ModelPropertyValue.OnUnderlyingModelChanged();
        } 
 
        // 
        // Called when the sub-property of the underlying ModelProperty changes. 
        // 
        protected override void OnUnderlyingSubModelChangedCore()
        {
            _valueCache.ClearSubValueRelatedCacheItems(); 
        }
 
        //  
        // Creates new instance of ModelPropertyValue
        //  
        // New instance of ModelPropertyValue
        protected override PropertyValue CreatePropertyValueInstance()
        {
            return new ModelPropertyValue(this); 
        }
 
        //  
        // Opens a new ModelEditingScope
        //  
        // Change description (may be null)
        // A new, opened ModelEditingScope
        internal override ModelEditingScope BeginEdit(string description)
        { 
            return description == null ? FirstModelProperty.Parent.BeginEdit() : FirstModelProperty.Parent.BeginEdit(description);
        } 
 
        // IPropertyFilterTarget Members
 
        // 
        // IPropertyFilterTarget method.  We override the default behavior which matches
        // both property DisplayName as well as the property Type name.
        //  
        // the predicate to match against
        // true if there is a match 
        public override bool MatchesPredicate(PropertyFilterPredicate predicate) 
        {
            return predicate == null ? false : predicate.Match(this.DisplayName); 
        }


        // IComparable Members 

        //  
        // Compares 'this' with the object passed into it using the ModelPropertyEntryComparer, 
        // which looks at both PropertyOrder as well as DisplayName to do the comparison
        //  
        // Object to compare this instance to
        // Comparison result
        public int CompareTo(object obj)
        { 
            return PropertyEntryPropertyOrderComparer.Instance.Compare(this, obj);
        } 
 

        //  
        // Debuging-friendly ToString()
        // 
        // 
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] 
        public override string ToString()
        { 
            try 
            {
                if (string.Equals(this.PropertyName, this.DisplayName)) 
                {
                    return string.Format(CultureInfo.CurrentCulture, "{0} (PropertyEntry)", this.PropertyName);
                }
                else 
                {
                    return string.Format(CultureInfo.CurrentCulture, "{0} (\"{1}\" - PropertyEntry)", this.PropertyName, this.DisplayName); 
                } 
            }
            catch 
            {
                return base.ToString();
            }
        } 

        // Cached values that need to be nixed when the underlying ModelProperty changes 
        // (ie. someone calls SetProperty()).  Pretty much everything in here is an "expensive" 
        // calculation which requires us to evaluate some attributes associated with the given
        // property or a set of properties, so we cache the return values and keep that cache 
        // in a single place so that it's easy to know what needs to be ----d when the underlying
        // ModelProperties change.
        private class CachedValues
        { 

            private static readonly PropertyValueEditor NoPropertyValueEditor = new PropertyValueEditor(); 
            private static readonly PropertyOrder NoPropertyOrder = PropertyOrder.CreateAfter(PropertyOrder.Default); 
            private static readonly TypeConverter NoTypeConverter = new TypeConverter();
            private static readonly ValueSerializer NoSerializer = new NoValueSerializer(); 
            private static readonly Type NoCommonValueType = typeof(CachedValues); // some private type that we can use as a marker
            private static readonly List NoCategoryEditorTypes = new List();
            private static readonly PropertyValueSource NoSource = new NoPropertyValueSource();
 
            private ModelPropertyEntry _parent;
 
            // Cached values 
            private string _displayName;
            private string _categoryName; 
            private string _description;
            private bool? _isAdvanced;
            private bool? _isBrowsable;
            private bool? _isReadOnly; 
            private bool? _isAttached;
            private ArrayList _standardValues; 
            private bool? _standardValuesExclusive; 
            private bool? _standardValuesSupported;
            private PropertyValueEditor _propertyValueEditor; 
            private bool? _isMixedValue;
            private PropertyValueSource _source;
            private ModelPropertyEntryCollection _subProperties;
            private ModelPropertyValueCollection _collection; 
            private TypeConverter _converter;
            private ValueSerializer _valueSerializer; 
            private Type _commonValueType; 
            private PropertyOrder _propertyOrder;
            private IEnumerable _categoryEditorTypes; 

            public CachedValues(ModelPropertyEntry parent)
            {
                _parent = parent; 
            }
 
            //  
            // Gets the display name of the contained property, if any.
            // Defaults to property name if none is found. 
            // 
            public string DisplayName
            {
                get { 
                    if (_displayName == null)
                    { 
                        _displayName = 
                            ExtensibilityAccessor.GetDisplayName(_parent.FirstModelProperty) ??
                            _parent.PropertyName; 
                    }

                    Fx.Assert(_displayName != null, "_displayName should not be null");
                    return _displayName; 
                }
            } 
 
            // 
            // Pick the first category name 
            // 
            public string CategoryName
            {
                get { 
                    if (_categoryName == null)
                    { 
                        _categoryName = ExtensibilityAccessor.GetCategoryName(_parent.FirstModelProperty); 
                    }
 
                    Fx.Assert(_categoryName != null, "_categoryName should not be null");
                    return _categoryName;
                }
            } 

            //  
            // Pick the first description 
            // 
            public string Description 
            {
                get {
                    if (_description == null)
                    { 
                        _description = ExtensibilityAccessor.GetDescription(_parent.FirstModelProperty);
                    } 
 
                    Fx.Assert(_description != null, "_description should not be null");
                    return _description; 
                }
            }

            //  
            // OR mutliple values of IsAdvanced together
            //  
            public bool IsAdvanced 
            {
                get { 
                    if (_isAdvanced == null)
                    {
                        _isAdvanced = false;
                        for (int i = 0; i < _parent._properties.Count; i++) 
                        {
                            _isAdvanced |= ExtensibilityAccessor.GetIsAdvanced(_parent._properties[i]); 
                            if (_isAdvanced == true) 
                            {
                                break; 
                            }
                        }
                    }
 
                    Fx.Assert(_isAdvanced != null, "_isAdvanced should not be null");
                    return (bool)_isAdvanced; 
                } 
            }
 
            // 
            // AND multiple values of IsBrowsable together
            // 
            public bool IsBrowsable 
            {
                get { 
                    if (_isBrowsable == null) 
                    {
                        _isBrowsable = true; 
                        for (int i = 0; i < _parent._properties.Count; i++)
                        {

                            // Look for the BrowsableAttribute 
                            bool? temp = ExtensibilityAccessor.IsBrowsable(_parent._properties[i]);
 
                            // Go by the IsReadOnly flag, if not found 
                            if (temp == null)
                            { 
                                temp = !this.IsReadOnly;
                            }

                            // AND multiple values together 
                            _isBrowsable &= (bool)temp;
 
                            if (_isBrowsable == false) 
                            {
                                break; 
                            }
                        }
                    }
 
                    Fx.Assert(_isBrowsable != null, "_isBrowsable should not be null");
                    return (bool)_isBrowsable; 
                } 
            }
 
            // 
            // Gets a flags indicating whether this property is read only.
            // 
            public bool IsReadOnly 
            {
                get { 
                    if (_isReadOnly == null) 
                    {
 
                        _isReadOnly = ExtensibilityAccessor.IsReadOnly(
                            _parent._properties,
                            new ExtensibilityAccessor.IsMixedValueEvaluator(delegate()
                        { 
                            return this.IsMixedValue;
                        })); 
 
                        Fx.Assert(_isReadOnly != null, "_isReadOnly should not be null");
                    } 

                    return (bool)_isReadOnly;
                }
            } 

            //  
            // Merge collection of standard values and only present the subset that exists in all. 
            // We do fancy magic here because presenting the user with invalid set of StandardValues
            // could actually cause bad things to happen (read: exceptions when the value is actually changed) 
            // 
            public ICollection StandardValues
            {
                get { 
                    if (_standardValues == null)
                    { 
 
                        // Note: this.Converter will return the converter associated with _parent._properties[0]
                        if (ExtensibilityAccessor.GetStandardValuesSupported(this.Converter)) 
                        {
                            _standardValues = ExtensibilityAccessor.GetStandardValues(this.Converter);
                        }
 
                        if (_standardValues == null)
                        { 
                            _standardValues = new ArrayList(); 
                        }
 
                        for (int i = 1; i < _parent._properties.Count && _standardValues.Count > 0; i++)
                        {
                            ArrayList nextSetOfValues = null;
 
                            if (ExtensibilityAccessor.GetStandardValuesSupported(_parent._properties[i].Converter))
                            { 
                                nextSetOfValues = ExtensibilityAccessor.GetStandardValues(_parent._properties[i].Converter); 
                            }
 
                            if (nextSetOfValues == null || nextSetOfValues.Count == 0)
                            {
                                // The AND of something and nothing = nothing, so clear any remaining list and exit
                                _standardValues.Clear(); 
                                break;
                            } 
 
                            for (int j = 0; j < _standardValues.Count; j++)
                            { 

                                object expectedValue = _standardValues[j];

                                if (!nextSetOfValues.Contains(expectedValue)) 
                                {
                                    _standardValues.RemoveAt(j); 
                                    j--; 
                                    continue;
                                } 
                            }
                        }
                    }
 
                    Fx.Assert(_standardValues != null, "_standardValues should not be null");
                    return _standardValues; 
                } 
            }
 
            // 
            // Gets a flag indicating whether the list of StandardValues is complete
            // or whether the user can type a value that's different from the ones in the list
            //  
            public bool StandardValuesExclusive
            { 
                get { 
                    if (_standardValuesExclusive == null)
                    { 
                        _standardValuesExclusive = (this.Converter == null || this.Converter.GetStandardValuesExclusive());
                    }

                    Fx.Assert(_standardValuesExclusive != null, "_standardValuesExclusive should not be null"); 
                    return (bool)_standardValuesExclusive;
                } 
            } 

            //  
            // Gets a flag indicating whether the StandardValues list has any contents.
            // 
            public bool StandardValuesSupported
            { 
                get {
                    if (_standardValuesSupported == null) 
                    { 
                        _standardValuesSupported = (this.Converter != null && this.Converter.GetStandardValuesSupported());
                    } 

                    Fx.Assert(_standardValuesSupported != null, "_standardValuesSupported should not be null");
                    return (bool)_standardValuesSupported;
                } 
            }
 
            //  
            // Pick the editor of the first ModelProperty
            //  
            public PropertyValueEditor PropertyValueEditor
            {
                get {
                    if (_propertyValueEditor == null) 
                    {
 
                        _propertyValueEditor = 
                            ExtensibilityAccessor.GetCustomPropertyValueEditor(_parent.FirstModelProperty) ??
                            ExtensibilityAccessor.GetSubPropertyEditor(_parent.FirstModelProperty); 

                        if (_propertyValueEditor == null && _parent.PropertyType == typeof(bool))
                        {
                            _propertyValueEditor = new BoolViewEditor(); 
                        }
 
                        _propertyValueEditor = _propertyValueEditor == null ? NoPropertyValueEditor : _propertyValueEditor; 
                    }
 
                    return _propertyValueEditor == NoPropertyValueEditor ? null : _propertyValueEditor;
                }
            }
 
            public bool IsMixedValue
            { 
                get { 
                    if (_isMixedValue == null)
                    { 

                        _isMixedValue = false;

                        if (_parent._properties.Count > 1) 
                        {
 
                            object mergedValue = null; 
                            string mergedValueString = null;
                            ValueSerializer valueSerializer = null; 

                            for (int i = 0; i < _parent._properties.Count; i++)
                            {
                                ModelProperty property = _parent._properties[i]; 
                                if (i == 0)
                                { 
 
                                    // Note: Calling GetValue on ModelProperty has the potential to
                                    // to reset internal stores and, even though the value doesn't change, 
                                    // we get a value changed notification.  That notification clears
                                    // our _isMixedValue, which, in fact, we want to retain.
                                    //
                                    bool oldIsMixedValue = (bool)_isMixedValue; 
                                    mergedValue = ModelUtilities.GetSafeRawValue(property);
                                    _isMixedValue = oldIsMixedValue; 
                                } 
                                else
                                { 

                                    // See comment above
                                    bool oldIsMixedValue = (bool)_isMixedValue;
                                    object nextValue = ModelUtilities.GetSafeRawValue(property); 
                                    _isMixedValue = oldIsMixedValue;
 
                                    // Are the objects equal? 
                                    if (object.Equals(mergedValue, nextValue))
                                    { 
                                        continue;
                                    }

                                    // No, so if any of them is null, we might as well bail 
                                    if (mergedValue == null || nextValue == null)
                                    { 
                                        _isMixedValue = true; 
                                        break;
                                    } 

                                    valueSerializer = valueSerializer ?? this.ValueSerializer;

                                    // If there is no ValueSerializer found, we can't 
                                    // be clever and need to bail
                                    if (valueSerializer == null) 
                                    { 
                                        _isMixedValue = true;
                                        break; 
                                    }

                                    // If we can't even convert the original value to string,
                                    // there is nothing to compare, so we bail 
                                    // the CanConvertToString call may throw an ArgumentException, for
                                    // example if mergedValue isn't a supported type 
                                    try 
                                    {
                                        if (mergedValueString == null && 
                                            !valueSerializer.CanConvertToString(mergedValue, null))
                                        {
                                            _isMixedValue = true;
                                            break; 
                                        }
                                    } 
                                    catch (ArgumentException) 
                                    {
                                        _isMixedValue = true; 
                                        break;
                                    }

                                    if (mergedValueString == null) 
                                    {
                                        mergedValueString = valueSerializer.ConvertToString(mergedValue, null); 
                                    } 

                                    // Finally, check to see if the nextValue can be converted to string 
                                    // and, if so, compare it to the mergedValue.
                                    if (!valueSerializer.CanConvertToString(nextValue, null) ||
                                        string.CompareOrdinal(mergedValueString, valueSerializer.ConvertToString(nextValue, null)) != 0)
                                    { 
                                        _isMixedValue = true;
                                        break; 
                                    } 
                                }
                            } 
                        }

                    }
 
                    return (bool)_isMixedValue;
                } 
            } 

            //  
            // Gets the source of the given property
            // 
            public PropertyValueSource Source
            { 
                get {
                    if (_source == null && this.IsMixedValue) 
                    { 
                        _source = NoSource;
                    } 

                    if (_source == null)
                    {
 
                        foreach (ModelProperty property in _parent._properties)
                        { 
 
                            if (_source == null)
                            { 
                                _source = ExtensibilityAccessor.GetPropertySource(property);

                                // Default value if we can't figure out anything else (this should never happen)
                                Fx.Assert(_source != null, "Could not figure out the source for property " + _parent.PropertyName); 
                                _source = _source ?? DependencyPropertyValueSource.Local;
                            } 
                            else if (_source != ExtensibilityAccessor.GetPropertySource(property)) 
                            {
                                _source = NoSource; 
                                break;
                            }
                        }
                    } 

                    return _source == NoSource ? null : _source; 
                } 
            }
 
            public ModelPropertyEntryCollection SubProperties
            {
                get {
                    if (_subProperties == null) 
                    {
                        _subProperties = new ModelPropertyEntryCollection(_parent); 
                    } 

                    return _subProperties; 
                }
            }

            public bool CollectionInstanceExists 
            {
                get { 
                    return _collection != null; 
                }
            } 

            public ModelPropertyValueCollection Collection
            {
                get { 
                    if (_collection == null)
                    { 
                        _collection = new ModelPropertyValueCollection(_parent.ModelPropertyValue); 
                    }
 
                    return _collection;
                }
            }
 
            // 
            // Pick the first converter 
            //  
            public TypeConverter Converter
            { 
                get {
                    if (_converter == null)
                    {
                        _converter = ExtensibilityAccessor.GetTypeConverter(_parent.FirstModelProperty) ?? NoTypeConverter; 
                    }
 
                    return _converter == NoTypeConverter ? null : _converter; 
                }
            } 

            // 
            // Gets the Type of value instance for this property.  For multi-properties,
            // CommonValueType returns the Type of all properties if it matches, null otherwise. 
            // 
            public Type CommonValueType 
            { 
                get {
                    if (_commonValueType == null) 
                    {

                        foreach (ModelProperty modelProperty in _parent.ModelPropertySet)
                        { 
                            object value = modelProperty.ComputedValue;
                            if (value != null) 
                            { 
                                Type valueType = value.GetType();
 
                                if (_commonValueType == null)
                                {
                                    _commonValueType = valueType;
                                } 
                                else if (_commonValueType != valueType)
                                { 
                                    _commonValueType = NoCommonValueType; 
                                    break;
                                } 
                            }
                            else
                            {
                                _commonValueType = NoCommonValueType; 
                                break;
                            } 
                        } 

                        _commonValueType = _commonValueType ?? NoCommonValueType; 
                    }

                    return _commonValueType == NoCommonValueType ? null : _commonValueType;
                } 
            }
 
            //  
            // Pick the first PropertyOrder
            //  
            public PropertyOrder PropertyOrder
            {
                get {
                    if (_propertyOrder == null) 
                    {
                        _propertyOrder = ExtensibilityAccessor.GetPropertyOrder(_parent.FirstModelProperty); 
                        _propertyOrder = _propertyOrder ?? NoPropertyOrder; 
                    }
 
                    return _propertyOrder == NoPropertyOrder ? null : _propertyOrder;
                }
            }
 
            // 
            // Gets a list of CategoryEditor types associated with this PropertyEntry 
            //  
            public IEnumerable CategoryEditorTypes
            { 
                get {
                    if (_categoryEditorTypes == null)
                    {
                        if (_parent.FirstModelProperty.IsAttached) 
                        {
                            _categoryEditorTypes = ExtensibilityAccessor.GetCategoryEditorTypes(_parent.FirstModelProperty.AttachedOwnerType); 
                        } 
                        _categoryEditorTypes = _categoryEditorTypes ?? NoCategoryEditorTypes;
                    } 

                    return _categoryEditorTypes == NoCategoryEditorTypes ? null : _categoryEditorTypes;
                }
            } 

            public bool IsAttached 
            { 
                get {
                    if (_isAttached == null) 
                    {
                        _isAttached = _parent.PropertyName.IndexOf('.') > -1;
                    }
 
                    return (bool)_isAttached;
                } 
            } 

            //  
            // Gets the ValueSerializer corresponding to the property type
            // 
            private ValueSerializer ValueSerializer
            { 
                get {
                    if (_valueSerializer == null) 
                    { 
                        _valueSerializer = ValueSerializer.GetSerializerFor(_parent.PropertyType) ?? NoSerializer;
                    } 

                    return _valueSerializer == NoSerializer ? null : _valueSerializer;
                }
            } 

            // Clear everything this class caches 
            public void ClearAll() 
            {
                _categoryName = null; 
                _description = null;
                _isAdvanced = null;
                _isBrowsable = null;
                _propertyValueEditor = null; 
                _propertyOrder = null;
                _categoryEditorTypes = null; 
                _displayName = null; 

                // Internal properties we don't bind to and, hence, 
                // don't need to fire PropertyChanged event:
                _isAttached = null;

                ClearValueRelatedCacheItems(); 

                _parent.OnPropertyChanged("CategoryName"); 
                _parent.OnPropertyChanged("Description"); 
                _parent.OnPropertyChanged("IsAdvanced");
                _parent.OnPropertyChanged("IsBrowsable"); 
                _parent.OnPropertyChanged("PropertyValueEditor");
                _parent.OnPropertyChanged("PropertyOrder");
                _parent.OnPropertyChanged("CategoryEditorTypes");
                _parent.OnPropertyChanged("DisplayName"); 
            }
 
            // Clear value-related things that this class caches 
            public void ClearValueRelatedCacheItems()
            { 
                _subProperties = null;
                _collection = null;
                _standardValues = null;
                _standardValuesExclusive = null; 
                _converter = null;
                _commonValueType = null; 
                _source = null; 
                _isReadOnly = null;
                _valueSerializer = null; 

                ClearSubValueRelatedCacheItems();

                _parent.OnPropertyChanged("StandardValues"); 
                _parent.OnPropertyChanged("StandardValuesExclusive");
                _parent.OnPropertyChanged("Converter"); 
                _parent.OnPropertyChanged("CommonValueType"); 
                _parent.OnPropertyChanged("IsReadOnly");
 
                // The following properties are only exposed by ModelPropertyEntry, not PropertyEntry.
                // People should bind to these properties through the PropertyValue.
                // However, if they ---- up in Xaml, the binding will still work and if that happens
                // we should try to update them when things change. 
                _parent.OnPropertyChanged("SubProperties");
                _parent.OnPropertyChanged("Collection"); 
                _parent.OnPropertyChanged("Source"); 
            }
 
            public void ClearSubValueRelatedCacheItems()
            {
                _isMixedValue = null;
 
                // The following property is only exposed by ModelPropertyEntry, not PropertyEntry.
                // People should bind to this property through the PropertyValue. 
                // However, if they ---- up in Xaml, the binding will still work and if that happens 
                // we should try to update them when things change.
                _parent.OnPropertyChanged("IsMixedValue"); 
            }

            private class NoPropertyValueSource : PropertyValueSource
            { 
                public NoPropertyValueSource()
                { 
                } 
            }
 
            private class NoValueSerializer : ValueSerializer
            {
                public NoValueSerializer()
                { 
                }
            } 
        } 
    }
} 

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

10814,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Model/ModelCategoryEntry.cs/1438166/ModelCategoryEntry.cs,4/26/2010 8:54:39 AM,13364
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Model
{ 
    using System;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Collections.Specialized;
    using System.Diagnostics; 
    using System.Activities.Presentation.PropertyEditing;
    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.Data;
    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.PropertyInspector;
    using System.Activities.Presentation; 

    //  
    // Cider's concrete implementation of CategoryEntry (CategoryBase comes from Sparkle 
    // and it has a few extra goodies that we want to reuse).  This class implements
    // INotifyCollectionChanged.  We need to push this implementation to the base class 
    // in v2.
    // 
    internal class ModelCategoryEntry : CategoryBase, INotifyCollectionChanged
    { 

        private ObservableCollectionWorkaround _basicProperties; 
        private ObservableCollectionWorkaround _advancedProperties; 

        //  
        // Basic ctor
        // 
        // Localized name for this category
        public ModelCategoryEntry(string categoryName) : base(categoryName) 
        {
            _basicProperties = new ObservableCollectionWorkaround(); 
            _advancedProperties = new ObservableCollectionWorkaround(); 
        }
 
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        // 
        // Gets the advanced properties contained in this category 
        // 
        public override ObservableCollection AdvancedProperties 
        { 
            get {
                return _advancedProperties; 
            }
        }

        //  
        // Gets the basic properties contained in this category
        //  
        public override ObservableCollection BasicProperties 
        {
            get { 
                return _basicProperties;
            }
        }
 
        // 
        // Gets a flag indicating whether this category contains any properties 
        //  
        internal bool IsEmpty
        { 
            get {
                return _advancedProperties.Count + _basicProperties.Count == 0;
            }
        } 

        //  
        // Returns either the basic or the advanced bucket based on the IsAdvanced flag 
        // set in the PropertyEntry itself
        //  
        // Property to examine
        // The corresponding basic or advanced bucket
        internal ObservableCollectionWorkaround GetBucket(PropertyEntry property)
        { 
            if (property == null)
            { 
                throw FxTrace.Exception.ArgumentNull("property"); 
            }
            return property.IsAdvanced ? _advancedProperties : _basicProperties; 
        }

        // 
        // Adds the given property to the specified property bucket (use 
        // ModelCategoryEntry.BasicProperties, ModelCategoryEntry.AdvancedProperties, or
        // ModelCategoryEntry.GetBucket()) sorted using the specified comparer. 
        //  
        // Property to add
        // Property bucket to populate 
        // Sort algorithm to use
        // If set to true, NotifyCollectionChanged event is fired
        internal void Add(
            PropertyEntry property, 
            ObservableCollection bucket,
            IComparer comparer) 
        { 
            Add(property, bucket, comparer, true);
        } 

        //
        // Adds the given property to the specified property bucket (use
        // ModelCategoryEntry.BasicProperties, ModelCategoryEntry.AdvancedProperties, or 
        // ModelCategoryEntry.GetBucket()) sorted using the specified comparer.
        // 
        private void Add( 
            PropertyEntry property,
            ObservableCollection bucket, 
            IComparer comparer,
            bool fireCollectionChangedEvent)
        {
 
            if (property == null)
            { 
                throw FxTrace.Exception.ArgumentNull("property"); 
            }
            if (bucket == null) 
            {
                throw FxTrace.Exception.ArgumentNull("bucket");
            }
            if (comparer == null) 
            {
                throw FxTrace.Exception.ArgumentNull("comparer"); 
            } 

            ObservableCollectionWorkaround castBucket = bucket as ObservableCollectionWorkaround; 
            int insertionIndex = 0;

            if (castBucket == null)
            { 
                Debug.Fail("Invalid property bucket.  The property sort order will be broken.");
            } 
            else 
            {
                insertionIndex = castBucket.BinarySearch(property, comparer); 
                if (insertionIndex < 0)
                {
                    insertionIndex = ~insertionIndex;
                } 
            }
 
            bucket.Insert(insertionIndex, property); 

            if (fireCollectionChangedEvent) 
            {
                FirePropertiesChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property));
            }
        } 

        //  
        // Removes and re-adds the specified property from this category, if it existed 
        // there to begin with.  Noop otherwise.
        // 
        // Use this method to refresh the cate----zation of a property if it suddenly
        // becomes Advanced if it was Basic before, or if its IsBrowsable status changes.
        // 
        // Property to refresh 
        // Property bucket to repopulate
        // Comparer to use to reinsert the given property in its new place 
        internal void Refresh(ModelPropertyEntry property, ObservableCollection bucket, IComparer sortComparer) 
        {
            if (property == null) 
            {
                throw FxTrace.Exception.ArgumentNull("property");
            }
            if (bucket != _basicProperties && bucket != _advancedProperties) 
            {
                Debug.Fail("Invalid bucket specified.  Property was not refreshed."); 
                return; 
            }
 
            // Let's see if we know about this property
            ObservableCollectionWorkaround collection;
            collection = _advancedProperties;
 
            int index = collection.BinarySearch(property, null);
            if (index < 0) 
            { 
                collection = _basicProperties;
                index = collection.BinarySearch(property, null); 
            }

            // If not, noop
            if (index < 0) 
            {
                return; 
            } 

            // We know about this property, so refresh it.  It may have changed 
            // somehow (eg. switched from basic to advanced, become hidden, etc.)
            // so make sure it's thrown into the right bucket.
            collection.RemoveAt(index);
            Add(property, bucket, sortComparer, false); 
        }
 
        //  
        // This is a work-around fix because Blend's CategoryBase does not handle null filters (valid value)
        // correctly.  We need to ask Blend to eventually fix this issue. 
        // 
        // Filter to apply, can be null
        public override void ApplyFilter(PropertyFilter filter)
        { 
            if (filter == null)
            { 
                this.MatchesFilter = true; 
                this.BasicPropertyMatchesFilter = true;
                this.AdvancedPropertyMatchesFilter = true; 

                foreach (PropertyEntry property in this.BasicProperties)
                {
                    property.ApplyFilter(filter); 
                }
 
                foreach (PropertyEntry property in this.AdvancedProperties) 
                {
                    property.ApplyFilter(filter); 
                }
            }
            else
            { 
                base.ApplyFilter(filter);
            } 
        } 

        // Another Blend work-around - we expose all properties through the OM, not just the 
        // Browsable ones.  However, as a result, we need to cull the non-browsable ones from
        // consideration.  Otherwise, empty categories may appear.
        protected override bool DoesPropertyMatchFilter(PropertyFilter filter, PropertyEntry property)
        { 
            property.ApplyFilter(filter);
 
            bool isBrowsable = true; 
            ModelPropertyEntry modelPropertyEntry = property as ModelPropertyEntry;
            if (modelPropertyEntry != null) 
            {
                //display given property if it is browsable or
                isBrowsable = modelPropertyEntry.IsBrowsable ||
                    // it may not be browsable, but if there is a category editor associated - display it anyway 
                    (this.CategoryEditors != null && this.CategoryEditors.Count != 0);
            } 
 
            return isBrowsable && property.MatchesFilter;
        } 

        // 
        // Sets the Disassociated flag on all contained properties to True
        //  
        internal void MarkAllPropertiesDisassociated()
        { 
            MarkAllPropertiesDisassociated(_basicProperties); 
            MarkAllPropertiesDisassociated(_advancedProperties);
        } 

        // 
        // Sets the Disassociated flag on all contained attached properties to True
        //  
        internal void MarkAttachedPropertiesDisassociated()
        { 
            MarkAttachedPropertiesDisassociated(_basicProperties); 
            MarkAttachedPropertiesDisassociated(_advancedProperties);
        } 

        // 
        // Removes all properties from this category whose Disassociated flag is set to True
        //  
        internal void CullDisassociatedProperties()
        { 
            bool propertiesCulled = false; 
            propertiesCulled |= CullDisassociatedProperties(_basicProperties);
            propertiesCulled |= CullDisassociatedProperties(_advancedProperties); 

            if (propertiesCulled)
            {
                FirePropertiesChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
            }
        } 
 
        private static void MarkAllPropertiesDisassociated(ObservableCollectionWorkaround propertyList)
        { 
            foreach (ModelPropertyEntry property in propertyList)
            {
                property.Disassociated = true;
            } 
        }
 
        private static void MarkAttachedPropertiesDisassociated(ObservableCollectionWorkaround propertyList) 
        {
            foreach (ModelPropertyEntry property in propertyList) 
            {
                if (property.IsAttached)
                {
                    property.Disassociated = true; 
                }
            } 
        } 

        private static bool CullDisassociatedProperties(ObservableCollectionWorkaround propertyList) 
        {
            bool propertiesCulled = false;
            for (int i = propertyList.Count - 1; i >= 0; i--)
            { 
                ModelPropertyEntry property = (ModelPropertyEntry)propertyList[i];
                if (property.Disassociated) 
                { 
                    property.Disconnect();
                    propertyList.RemoveAt(i); 
                    propertiesCulled = true;
                }
            }
 
            return propertiesCulled;
        } 
 
        // INotifyCollectionChanged Members
 
        private void FirePropertiesChanged(NotifyCollectionChangedEventArgs collectionChangedEventArgs)
        {
            // Fire both "Properties" changed events
            OnPropertyChanged("Properties"); 
            OnPropertyChanged("Item[]");
 
            // as well as the appropriate collection-changed event 
            if (CollectionChanged != null)
            { 
                CollectionChanged(this, collectionChangedEventArgs);
            }
        }
 
    }
} 

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

10815,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/FromExpression/Framework/Tolerances.cs/1305376/Tolerances.cs,4/26/2010 8:54:39 AM,1207
// -------------------------------------------------------------------- 
// Description:
// Provides helper functions handling move and hit detection
// tolerances.
// 
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// ------------------------------------------------------------------- 
 
//Cider comment:
//  - Class has many members that we don't use. 
//  - I have removed them to avoid FXCop warning and lowering code coverage

//From \\authoring\Sparkle\Source\1.0.1083.0\Common\Source\Framework
namespace System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework 
{
    using System; 
    using System.Windows; 
    using System.Windows.Media.Media3D;
    internal static class Tolerances 
    {
        //Cider private static readonly double ZeroThreshold = 2.2204460492503131e-015;
        private const double ZeroThreshold = 2.2204460492503131e-015;
 
        public static bool NearZero(double d)
        { 
            return Math.Abs(d) < Tolerances.ZeroThreshold; 
        }
 
    }
}

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

10816,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/ExtensibilityAccessor.cs/1305376/ExtensibilityAccessor.cs,4/26/2010 8:54:39 AM,38108
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Markup; 

    using System.Activities.Presentation.Model; 
    using System.Activities.Presentation.PropertyEditing; 

    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework; 
    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.PropertyInspector;

    using System.Activities.Presentation.Internal.PropertyEditing.Editors;
    using ModelUtilities = System.Activities.Presentation.Internal.PropertyEditing.Model.ModelUtilities; 

    //  
    // Static helper class that contains all extensibility-related code.  No other code 
    // under PropertyEditing should be looking up attributes and interpretting them.
    // In most cases, the methods here delegate to Sparkle's binaries to make sure that 
    // both products behave consistently.
    // 
    internal static class ExtensibilityAccessor
    { 

        // Cache of Types to their respective DefaultProperties 
        private static Dictionary _defaultPropertyCache = new Dictionary(); 

        //  
        // Gets the name of the category that the specified ModelProperty belongs to
        // 
        // ModelProperty to examine
        // Name of the category that the specified ModelProperty belongs to 
        public static string GetCategoryName(ModelProperty property)
        { 
            CategoryAttribute attribute = GetAttribute(property); 

            if (attribute == null || string.IsNullOrEmpty(attribute.Category)) 
            {
                return CategoryAttribute.Default.Category;
            }
            else 
            {
                return attribute.Category; 
            } 
        }
 
        // 
        // Gets the StandardValues that are exposed by the specified TypeConverter
        // 
        // TypeConverter to examine 
        // StandardValues that are exposed by the specified TypeConverter
        public static ArrayList GetStandardValues(TypeConverter converter) 
        { 
            if (converter == null)
            { 
                return null;
            }

            if (!converter.GetStandardValuesSupported()) 
            {
                return null; 
            } 

            ICollection values = converter.GetStandardValues(); 
            if (values == null)
            {
                return null;
            } 

            // unwrap ModelItems if that's what the converter gives us 
            ArrayList convertedValues = new ArrayList(values.Count); 
            foreach (object value in values)
            { 
                ModelItem item = value as ModelItem;
                if (item != null)
                {
                    convertedValues.Add(item.GetCurrentValue()); 
                }
                else 
                { 
                    convertedValues.Add(value);
                } 
            }

            return convertedValues;
        } 

        //  
        // Gets a flag indicating if a further call to GetStandardValues will 
        // give back a non-zero collection.
        //  
        // The type converter to check.
        // True if the type converter supports standard values.
        public static bool GetStandardValuesSupported(TypeConverter converter)
        { 
            return (converter != null && converter.GetStandardValuesSupported());
        } 
 
        // 
        // Look for and return any custom PropertyValueEditor defined for the specified ModelProperty 
        // 
        // ModelProperty to examine
        // A custom PropertyValueEditor for the specified ModelProperty (may be null)
        public static PropertyValueEditor GetCustomPropertyValueEditor(ModelProperty property) 
        {
            if (property == null) 
            { 
                return null;
            } 

            PropertyValueEditor editor = ExtensibilityMetadataHelper.GetValueEditor(property.Attributes, MessageLogger.Instance);

            //if property is a generic type, check for designer defined at generic type definition 
            if (editor == null && property.PropertyType.IsGenericType)
            { 
                Type genericType = property.PropertyType.GetGenericTypeDefinition(); 
                editor = ExtensibilityMetadataHelper.GetValueEditor(TypeDescriptor.GetAttributes(genericType), MessageLogger.Instance);
            } 

            return editor;
        }
        //  
        // Returns an instance of SubPropertyEditor if the specified ModelProperty can be edited
        // using sub-properties, null otherwise. 
        //  
        // ModelProperty to examine
        // An instance of SubPropertyEditor if the specified ModelProperty can be edited 
        // using sub-properties, null otherwise.
        public static PropertyValueEditor GetSubPropertyEditor(ModelProperty property)
        {
            if (property == null) 
            {
                return null; 
            } 

            if (property.Converter == null || 
                property.Converter.GetPropertiesSupported() == false)
            {
                // if it's a property of a generic type, check for converter defined at the property of generic type definition
                if (property.Parent.ItemType.IsGenericType) 
                {
                    Type genericType = property.Parent.ItemType.GetGenericTypeDefinition(); 
                    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(genericType); 
                    PropertyDescriptor propertyDescriptor = properties.Find(property.Name, false);
                    if (propertyDescriptor != null) 
                    {
                        // wrap the converter and check if it supports GetProperties()
                        TypeConverter converter = new ModelTypeConverter(((IModelTreeItem)property.Parent).ModelTreeManager, propertyDescriptor.Converter);
                        if (converter.GetPropertiesSupported()) 
                        {
                            return SubPropertyViewEditor.Instance; 
                        } 
                    }
                } 

                return null;
            }
 
            //Dont support Arrays
            if (typeof(Array).IsAssignableFrom(property.PropertyType)) 
            { 
                return null;
            } 

            return SubPropertyViewEditor.Instance;
        }
 
        // 
        // ----s open the specified Type and looks for EditorAttributes that represent 
        // CategoryEditors - returns the Types of those editors, if any are found, as a list 
        // 
        // Type to ---- open 
        // List of CategoryEditors associated with the specified type, if any.  Null otherwise.
        public static IEnumerable GetCategoryEditorTypes(Type ownerType)
        {
 
            List editorTypes = null;
 
            foreach (EditorAttribute editorAttribute in GetAttributes(ownerType)) 
            {
 
                // A ---- attempt at using the same extensibility code
                Type editorType = ExtensibilityMetadataHelper.GetCategoryEditorType(editorAttribute, MessageLogger.Instance);
                if (editorType == null)
                { 
                    continue;
                } 
 
                if (editorTypes == null)
                { 
                    editorTypes = new List();
                }

                editorTypes.Add(editorType); 
            }
 
            return editorTypes; 
        }
 
        // 
        // Decides whether the specified ModelProperty should be advanced
        // 
        // ModelProperty to look up 
        // True if the property should be advanced, false otherwise
        public static bool GetIsAdvanced(ModelProperty property) 
        { 
            EditorBrowsableAttribute browsable = GetAttribute(property);
 
            if (browsable == null)
            {
                return false;
            } 

            return browsable.State == EditorBrowsableState.Advanced; 
        } 

        //  
        // Decides whether the specified CategoryEditor should be advanced.
        // Note: Blend uses custom, baked-in logic to determine whether a given CategoryEditor
        // is advanced or not.  The logic is the same as the one here, but we can't share it
        // because they don't expose it.  In v2, this is definitely something we should share. 
        // 
        // CategoryEditor to look up 
        // True if the specified editor should be advanced, false otherwise 
        public static bool GetIsAdvanced(CategoryEditor editor)
        { 
            EditorBrowsableAttribute browsable = GetAttribute(editor.GetType());

            if (browsable == null)
            { 
                return false;
            } 
 
            return browsable.State == EditorBrowsableState.Advanced;
        } 

        // 
        // Looks up the DefaultPropertyAttribute on the given type and returns the default property,
        // if any. 
        // 
        // Type to look up 
        // Default property associated with the specified type, if any. 
        public static string GetDefaultProperty(Type type)
        { 
            if (type == null)
            {
                return null;
            } 

            string defaultProperty; 
            if (_defaultPropertyCache.TryGetValue(type, out defaultProperty)) 
            {
                return defaultProperty; 
            }

            DefaultPropertyAttribute dpa = GetAttribute(type);
            defaultProperty = dpa == null ? null : dpa.Name; 
            defaultProperty = defaultProperty == null ? null : defaultProperty.Trim();
            _defaultPropertyCache[type] = defaultProperty; 
            return defaultProperty; 
        }
 
        // 
        // Attempts to look up a custom display name from the DisplayNameAttribute.
        // Returns null if the attribute is not defined.
        //  
        // ModelProperty to examine
        // Custom DisplayName for the property, if any. 
        public static string GetDisplayName(ModelProperty property) 
        {
            DisplayNameAttribute displayNameAttribute = GetAttribute(property); 

            if (displayNameAttribute == null)
            {
                return null; 
            }
 
            string displayName = displayNameAttribute.DisplayName; 
            if (string.IsNullOrEmpty(displayName))
            { 
                return null;
            }

            return displayName; 
        }
 
        //  
        // Gets the description associated with the specified ModelProperty
        //  
        // ModelProperty to examine
        // The description associated with the specified ModelProperty
        public static string GetDescription(ModelProperty property)
        { 
            DescriptionAttribute description = GetAttribute(property);
 
            if (description == null || string.IsNullOrEmpty(description.Description)) 
            {
                return DescriptionAttribute.Default.Description; 
            }

            return description.Description;
        } 

        //  
        // Instantiates a TypeConverter from a potential TypeConverterAttribute, if one exists. 
        // 
        // ModelItem to examine 
        // Instantiated TypeConverter from a potential TypeConverterAttribute, if one exists,
        // null otherwise.
        public static TypeConverter GetTypeConverter(ModelItem item)
        { 
            return InstantiateTypeConverter(GetAttribute(item));
        } 
 
        // 
        // Gets the TypeConverter associated with the specified ModelProperty, returning 
        // null when no TypeConverter is found.
        // 
        // property to examine
        // Associated TypeConverter if one exists, null otherwise. 
        public static TypeConverter GetTypeConverter(ModelProperty property)
        { 
            return property == null ? null : property.Converter; 
        }
 
        // 
        // Computes the IsReadOnly flag for the specified set of properties, ORing
        // results together for sets of properties larger than 1.
        //  
        // Properties to examine
        // Delegate that evaluates the IsMixedValue flag for 
        // the passed in property values (added as an optimization, since we don't always require 
        // the value and it may be computationally expensive)
        // Flag indicating whether the set of properties is read only or not 
        public static bool IsReadOnly(List properties, IsMixedValueEvaluator isMixedValueEvaluator)
        {
            if (properties == null || properties.Count == 0)
            { 
                Debug.Fail("ExtensibilityAccessor.IsReadOnly: No properties specified.");
                return true; 
            } 

            Type propertyType = properties[0].PropertyType; 

            // ILists are readonly only if value is null
            if (typeof(IList).IsAssignableFrom(propertyType))
            { 

                if (OrReadOnlyValues(properties)) 
                { 
                    IList list = null;
                    if (isMixedValueEvaluator != null) 
                    {
                        list = isMixedValueEvaluator() ? null : (ModelUtilities.GetSafeRawValue(properties[0]) as IList);
                    }
                    else 
                    {
                        Debug.Fail("No delegate to evaluate IsMixedValue specified."); 
                    } 

                    if (list == null) 
                    {
                        return true;
                    }
                } 

                return false; 
            } 

            // Arrays and ICollections are readonly 
            if (typeof(Array).IsAssignableFrom(propertyType) || typeof(ICollection).IsAssignableFrom(propertyType))
            {
                return true;
            } 

            // Types that implement ONLY ICollection<> or ONLY IList<> (meaning they 
            // don't also implement ICollection or IList, which we handle above) 
            // are also readonly
            if (ModelUtilities.ImplementsICollection(propertyType) || ModelUtilities.ImplementsIList(propertyType)) 
            {
                return true;
            }
 
            // Otherwise, go off of the IsReadOnly value in ModelProperty
            return OrReadOnlyValues(properties); 
        } 

 
        // 
        // Looks up and returns the BrowsableAttribute on the specified property.
        // 
        // ModelProperty to examine 
        // True, if the property is marked as browsable, false if it is
        // marked as non-browsable, null if it is unmarked. 
        public static bool? IsBrowsable(ModelProperty property) 
        {
            if (property == null) 
            {
                return false;
            }
 
            // Check if the Browsable(true) attribute is explicitly defined.
            BrowsableAttribute browsable = GetAttribute(property); 
 
            // If explicit browsable then honor that.
            if (browsable != null) 
            {
                return browsable.Browsable;
            }
            return null; 
        }
 
        //  
        // Gets the PropertyOrder token associated with the given ModelProperty
        //  
        // ModelProperty to examine
        // Associated PropertyOrder token if one exists, null otherwise.
        public static PropertyOrder GetPropertyOrder(ModelProperty property)
        { 
            if (property == null)
            { 
                return null; 
            }
 
            PropertyOrderAttribute attr = GetAttribute(property);
            if (attr == null)
            {
                return null; 
            }
 
            return attr.Order; 
        }
 
        // 
        // Returns the list of NewItemTypesAttributes that are associated with the
        // specified ModelProperty.  Note that we should never be returning attributes
        // from any of the public methods of ExtensibilityAccessor.  The only reason 
        // why we do so here is to pass them to a Blend API that requires it.  However,
        // this is a design flaw and we should not follow suite elsewhere. 
        // This method is guaranteed not to return null. 
        // 
        // ModelProperty instance to look up 
        // List of NewItemTypesSttributes associated with the given ModelProperty.
        public static List GetNewItemTypesAttributes(ModelProperty property)
        {
 
            List newItemTypesList = new List();
 
            foreach (NewItemTypesAttribute newItemTypesAttribute in GetAttributes(property)) 
            {
 
                // if there is no custom ItemFactory defined
                if (newItemTypesAttribute.FactoryType == typeof(NewItemFactory))
                {
                    foreach (Type type in newItemTypesAttribute.Types) 
                    {
                        //Check if the type "IsConcreteWithDefaultCtor" 
                        if (EditorUtilities.IsConcreteWithDefaultCtor(type)) 
                        {
                            newItemTypesList.Add(new NewItemTypesAttribute(type)); 
                        }
                    }
                }
                else 
                {
                    newItemTypesList.Add(newItemTypesAttribute); 
                } 
            }
            return newItemTypesList; 
        }

        // 
        // Examines the specified ModelProperty for NewItemTypesAttributes and, if found, returns 
        // an enumerable of all NewItemFactoryTypeModels specified through them.
        //  
        // ModelProperty instance to look up 
        // Returns an enumerable of all NewItemFactoryTypeModels specified through custom
        // NewItemFactoryTypeModels, if any. 
        public static IEnumerable GetNewItemFactoryTypeModels(ModelProperty modelProperty, Size desiredIconSize)
        {
            List attributes = GetNewItemTypesAttributes(modelProperty);
            if (attributes == null) 
            {
                yield break; 
            } 

            foreach (NewItemTypesAttribute attribute in attributes) 
            {
                NewItemFactory factory = (NewItemFactory)Activator.CreateInstance(attribute.FactoryType);

                foreach (Type type in attribute.Types) 
                {
 
                    NewItemFactoryTypeModel model = null; 

                    if (attribute.FactoryType == typeof(NewItemFactory)) 
                    {
                        if (EditorUtilities.IsConcreteWithDefaultCtor(type))
                        {
                            model = new NewItemFactoryTypeModel(type, factory, MessageLogger.Instance); 
                        }
                    } 
                    else 
                    {
                        model = new NewItemFactoryTypeModel(type, factory, MessageLogger.Instance); 
                    }

                    if (model != null)
                    { 
                        model.DesiredSize = desiredIconSize;
                        yield return model; 
                    } 
                }
            } 
        }

        // 
        // Gets all relevant sub-properties from the given ModelItem 
        // 
        // Item to examine 
        // Sub-properties exposed by the given ModelItem 
        public static List GetSubProperties(ModelItem item)
        { 
            if (item == null)
            {
                return null;
            } 

            // First, see if there is a custom TypeConverter.  If so, get the subProperties 
            // from there.  Otherwise, get all subProperties including those that aren't browsable, 
            // since the Browsability call should be made by the UI, not by the model.
            return GetTypeConverterSubProperties(item) ?? GetAllSubProperties(item); 
        }

        // 
        // Gets all relevant sub-properties from the value of the specified 
        // ModelProperty
        //  
        // ModelProperty to examine 
        // Sub-properties exposed by the value of the specified ModelProperty
        public static List GetSubProperties(ModelProperty property) 
        {
            if (property.Value == null || ModelUtilities.GetSafeRawValue(property) == null)
            {
                return null; 
            }
 
            // First, see if there is a custom TypeConverter.  If so, get the subProperties 
            // from there.  Otherwise, get all subProperties including those that aren't browsable,
            // since the Browsability call should be made by the UI, not by the model. 
            return GetTypeConverterSubProperties(property) ?? GetAllSubProperties(property);
        }

        //  
        // try / catch wrapper artound Activator.CreateInstance()
        //  
        // Type to instantiate 
        // Instantiated object or null on error
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] 
        public static object SafeCreateInstance(Type type)
        {
            try
            { 
                return Activator.CreateInstance(type);
            } 
            catch 
            {
                // ignore errors... 
            }

            return null;
        } 

        //  
        // Returns the property source based on the following heuristic (in line with 
        // Blend's behavior):
        // 
        // Xaml                                    Source
        // -------------------------------------------------------------------
        // "123"                                   Local
        // "{Binding}"                             DataBound 
        // not specified (default value)           Default
        // not specified (inherited value)         Inherited 
        // not specified (from style)              Inherited 
        // "{DynamicResource ...}"                 LocalDynamicResource
        // "{StaticResource ...}"                  LocalStaticResource 
        // "{x:Static ...}"                        SystemResource
        // "{TemplateBinding ...}"                 TemplateBinding
        // "{CustomMarkup ...}"                    CustomMarkupExtension
        // 
        // 
        // Property to examine 
        // Source of the specified property, if any 
        public static PropertyValueSource GetPropertySource(ModelProperty property)
        { 
            if (property == null)
            {
                return null;
            } 

            ModelItem valueItem = property.Value; 
            PropertyValueSource source = null; 

            // Binding or any other known markup extension? 
            if (valueItem != null)
            {
                Type valueType = valueItem.ItemType;
 
                if (IsStaticExtension(valueType))
                { 
                    source = DependencyPropertyValueSource.SystemResource; 
                }
                else if (typeof(StaticResourceExtension).IsAssignableFrom(valueType)) 
                {
                    source = DependencyPropertyValueSource.LocalStaticResource;
                }
                else if (typeof(DynamicResourceExtension).IsAssignableFrom(valueType)) 
                {
                    source = DependencyPropertyValueSource.LocalDynamicResource; 
                } 
                else if (typeof(TemplateBindingExtension).IsAssignableFrom(valueType))
                { 
                    source = DependencyPropertyValueSource.TemplateBinding;
                }
                else if (typeof(Binding).IsAssignableFrom(valueType))
                { 
                    source = DependencyPropertyValueSource.DataBound;
                } 
                else if (typeof(MarkupExtension).IsAssignableFrom(valueType)) 
                {
                    source = DependencyPropertyValueSource.CustomMarkupExtension; 
                }
            }

            // If not, is this a local, inherited, or default value? 
            if (source == null)
            { 
 
                if (property.IsSet)
                { 
                    source = DependencyPropertyValueSource.Local;
                }
                else
                { 

                    object value = property.ComputedValue; 
 
                    if (object.Equals(value, property.DefaultValue))
                    { 
                        source = DependencyPropertyValueSource.DefaultValue;
                    }
                    else if (valueItem != null && valueItem.Source != property)
                    { 
                        source = DependencyPropertyValueSource.Inherited;
                    } 
                } 
            }
 
            return source;
        }

        // Helper method that ORs the ModelProperty.IsReadOnly values together and 
        // returns the result
        private static bool OrReadOnlyValues(List properties) 
        { 
            if (properties == null)
            { 
                return true;
            }

            for (int i = 0; i < properties.Count; i++) 
            {
                if (properties[i].IsReadOnly) 
                { 
                    return true;
                } 
            }

            return false;
        } 

        // Helper method to find if the propertyvalueeditor is reusable for the 
        // given properties collection. 
        public static bool IsEditorReusable(IEnumerable properties)
        { 
            if (properties == null)
            {
                return true;
            } 

            foreach(ModelProperty property in properties) 
            { 
                // even if one property says the editor is not reusable, then
                // the editor is not reusable for this whole list. 
                if (!ExtensibilityMetadataHelper.IsEditorReusable(property.Attributes))
                {
                    return false;
                } 
            }
            return true; 
        } 

        // Hack to deal with {x:Static ...} extensions.  The Cider Markup code currently 
        // replaces all StaticExtensions with internal versions of the same class.
        // Once bug 100647 is fixed this code can go away.
        private static bool IsStaticExtension(Type type)
        { 
            return type != null && (
                typeof(StaticExtension).IsAssignableFrom(type) || 
                string.Equals("System.Activities.Presentation.Internal.Xaml.Builtins.StaticExtension", type.FullName)); 
        }
 
        // Gets all subProperties from the TypeConverter, if one is explicitely specified
        private static List GetTypeConverterSubProperties(ModelItem item)
        {
            return GetTypeConverterSubPropertiesHelper(item, null); 
        }
 
        // Gets all subProperties from the TypeConverter, if one is explicitely specified 
        private static List GetTypeConverterSubProperties(ModelProperty property)
        { 
            TypeConverter propertySpecificConverter = property.Converter;
            return GetTypeConverterSubPropertiesHelper(property.Value, propertySpecificConverter);
        }
 
        private static List GetTypeConverterSubPropertiesHelper(ModelItem item, TypeConverter customConverter)
        { 
 
            if (item == null)
            { 
                return null;
            }

            List subProperties = null; 

            TypeConverter converter = customConverter; 
 
            if (converter == null)
            { 
                // See if there is a converter associated with the item type itself
                converter = ExtensibilityAccessor.GetTypeConverter(item);
            }
 
            if (converter != null)
            { 
                PropertyDescriptorCollection subPropertyDescriptors = 
                    converter.GetProperties(item.GetCurrentValue());
 
                if (subPropertyDescriptors != null && subPropertyDescriptors.Count > 0)
                {

                    foreach (PropertyDescriptor subPropertyDescriptor in subPropertyDescriptors) 
                    {
 
                        ModelProperty subProperty = item.Properties[subPropertyDescriptor.Name]; 

                        // We want to expose all properties through the model regardless of whether they 
                        // are browsable or not.  That distinction should be made by the UI utilizing it
                        if (subProperty != null)
                        {
 
                            if (subProperties == null)
                            { 
                                subProperties = new List(); 
                            }
 
                            subProperties.Add(subProperty);
                        }
                    }
                } 
            }
            return subProperties; 
        } 

        // Gets all subProperties that exist 
        private static List GetAllSubProperties(ModelItem item)
        {

            if (item == null) 
            {
                return null; 
            } 

            ModelPropertyCollection subModelProperties = item.Properties; 
            if (subModelProperties == null)
            {
                return null;
            } 

            List subProperties = null; 
 
            // We want to expose all properties through the model regardless of whether they
            // are browsable or not.  That distinction should be made by the UI utilizing it 
            foreach (ModelProperty subModelProperty in subModelProperties)
            {

                if (subProperties == null) 
                {
                    subProperties = new List(); 
                } 

                subProperties.Add(subModelProperty); 
            }

            return subProperties;
        } 

        // Gets all subProperties that exist 
        private static List GetAllSubProperties(ModelProperty property) 
        {
            return GetAllSubProperties(property.Value); 
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Propagating the error might cause VS to crash")]
        [SuppressMessage("Reliability", "Reliability108", Justification = "Propagating the error might cause VS to crash")] 
        private static TypeConverter InstantiateTypeConverter(TypeConverterAttribute typeConverterAttribute)
        { 
            if (typeConverterAttribute == null) 
            {
                return null; 
            }

            try
            { 
                Type typeConverterType = Type.GetType(typeConverterAttribute.ConverterTypeName);
                if (typeConverterType != null) 
                { 
                    return (TypeConverter)Activator.CreateInstance(typeConverterType);
                } 
            }
            catch (Exception)
            {
                // Ignore failures.  In the future, log these somewhere for 3rd parties to see and debug. 
            }
 
            return null; 
        }
 
        // GetAttributes() and GetAttribute()

        public static T GetAttribute(ModelProperty property) where T : Attribute
        { 
            return GetAttribute(property == null ? null : property.Attributes);
        } 
 
        public static T GetAttribute(ModelItem item) where T : Attribute
        { 
            return GetAttribute(item == null ? null : item.Attributes);
        }

        public static T GetAttribute(Type type) where T : Attribute 
        {
            return GetAttribute(type == null ? null : TypeDescriptor.GetAttributes(type)); 
        } 

        public static IEnumerable GetAttributes(ModelProperty property) where T : Attribute 
        {
            return GetAttributes(property == null ? null : property.Attributes);
        }
 
        public static IEnumerable GetAttributes(Type type) where T : Attribute
        { 
            return GetAttributes(type == null ? null : TypeDescriptor.GetAttributes(type)); 
        }
 
        // Note: Calling AttributeCollection[typeof(MyAttribute)] creates a default attribute if
        // the specified attribute is not found.  That's generally not what we want.
        public static T GetAttribute(AttributeCollection attributes) where T : Attribute
        { 
            T foundAttribute = null;
            if (attributes != null) 
            { 
                foreach (Attribute attribute in attributes)
                { 
                    if (typeof(T).IsAssignableFrom(attribute.GetType()))
                    {
                        foundAttribute = attribute as T;
                    } 
                }
            } 
 
            return foundAttribute;
        } 

        // Note: Calling AttributeCollection[typeof(MyAttribute)] creates a default attribute if
        // the specified attribute is not found.  That's generally not what we want.
        private static IEnumerable GetAttributes(AttributeCollection attributes) where T : Attribute 
        {
            if (attributes != null) 
            { 
                foreach (Attribute attribute in attributes)
                { 
                    if (typeof(T).IsAssignableFrom(attribute.GetType()))
                    {
                        yield return (T)attribute;
                    } 
                }
            } 
        } 

        //  
        // Delegate intended to wrap logic that evaluates the IsMixedValue flag of
        // some property or set of properties.
        // 
        // True if values are mixed, false otherwise 
        public delegate bool IsMixedValueEvaluator();
 
        // 
        private class MessageLogger : IMessageLogger
        { 

            private static MessageLogger _instance = new MessageLogger();

            public static MessageLogger Instance 
            { get { return _instance; } }
 
            public void Clear() 
            {
            } 

            public void Write(string text)
            {
                Debug.Write(text); 
            }
 
            public void WriteLine(string text) 
            {
                Debug.WriteLine(text); 
            }
        }
    }
} 

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

10817,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Editors/SubPropertyEditor.cs/1305376/SubPropertyEditor.cs,4/26/2010 8:54:39 AM,23176
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Editors
{ 
    using System;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel;
    using System.Globalization; 
    using System.Windows;
    using System.Windows.Automation.Peers;
    using System.Windows.Controls;
    using System.Windows.Data; 

    using System.Runtime; 
    using System.Activities.Presentation.Model; 
    using System.Activities.Presentation.PropertyEditing;
 
    using System.Activities.Presentation.Internal.PropertyEditing.FromExpression.Framework.PropertyInspector;

    using System.Activities.Presentation.Internal.PropertyEditing.Automation;
    using System.Activities.Presentation.Internal.PropertyEditing.Model; 
    using ModelUtilities = System.Activities.Presentation.Internal.PropertyEditing.Model.ModelUtilities;
    using System.Activities.Presentation.Internal.PropertyEditing.Resources; 
    using System.Activities.Presentation.Internal.PropertyEditing.Selection; 
    using System.Activities.Presentation.Internal.PropertyEditing.State;
 
    // 
    // We use the SubPropertyEditor to replace the entire property row
    // when the property exposes its subproperties.  This control is _not_
    // just used within the value-editing portion of a property row. 
    // We cheat because we can.
    //  
    internal class SubPropertyEditor : Control, INotifyPropertyChanged, ISelectionStop 
    {
 
        // 
        // PropertyEntry is used to store the currently displayed PropertyEntry
        // 
        public static readonly DependencyProperty PropertyEntryProperty = DependencyProperty.Register( 
            "PropertyEntry",
            typeof(PropertyEntry), 
            typeof(SubPropertyEditor), 
            new PropertyMetadata(null, new PropertyChangedCallback(OnPropertyEntryChanged)));
 
        // 
        // Boolean used to indicate whether the sub-properties are being shown or not.  As an optimization,
        // we don't actually expose the PropertyValue's sub-properties through SelectiveSubProperties until
        // the sub-property expando-pane has been open at least once. 
        // 
        public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register( 
            "IsExpanded", 
            typeof(bool),
            typeof(SubPropertyEditor), 
            new PropertyMetadata(false, new PropertyChangedCallback(OnIsExpandedChanged)));

        // 
        // Exposes the currently selected QuickType in the QuickType drop-down.  Essentially, 
        // the value of this DP is plumbed through to reflect the value of _quickTypeView.CurrentItem
        //  
        public static readonly DependencyProperty CurrentQuickTypeProperty = DependencyProperty.Register( 
            "CurrentQuickType",
            typeof(NewItemFactoryTypeModel), 
            typeof(SubPropertyEditor),
            new PropertyMetadata(null, new PropertyChangedCallback(OnCurrentQuickTypeChanged)));

        private ICollectionView _quickTypeView; 
        private ObservableCollection _quickTypeCollection;
        private bool _ignoreInternalChanges; 
        private bool _exposedSubProperties; 

        private ItemsControl _subPropertyListControl; 

        // 
        // Basic ctor
        //  
        public SubPropertyEditor()
        { 
            _quickTypeCollection = new ObservableCollection(); 

            _quickTypeView = CollectionViewSource.GetDefaultView(_quickTypeCollection); 
            _quickTypeView.CurrentChanged += new EventHandler(OnCurrentQuickTypeChanged);
        }

        // Automation 

        public event PropertyChangedEventHandler PropertyChanged; 
 
        // Internal event we fire for the sake of SubPropertyEditorAutomationPeer that
        // causes it to refresh its offered set of children 
        internal event EventHandler VisualsChanged;

        public PropertyEntry PropertyEntry
        { 
            get { return (PropertyEntry)this.GetValue(PropertyEntryProperty); }
            set { this.SetValue(PropertyEntryProperty, value); } 
        } 

        public bool IsExpanded 
        {
            get { return (bool)this.GetValue(IsExpandedProperty); }
            set { this.SetValue(IsExpandedProperty, value); }
        } 

        public NewItemFactoryTypeModel CurrentQuickType 
        { 
            get { return (NewItemFactoryTypeModel)this.GetValue(CurrentQuickTypeProperty); }
            set { this.SetValue(CurrentQuickTypeProperty, value); } 
        }

        // 
        // Gets a flag indicating whether QuickTypes exist 
        // 
        public bool HasQuickTypes 
        { 
            get {
                return _quickTypeCollection.Count > 0; 
            }
        }

        //  
        // Returns a list of available QuickTypes (collection of NewItemFactoryTypeModel instances)
        //  
        public ICollectionView QuickTypes 
        {
            get { 
                return _quickTypeView;
            }
        }
 
        // 
        // Exposes PropertyValue.SubProperties when the IsExpanded flag first gets set to true 
        // and forever thereafter (or at least until the current PropertyValue changes and we 
        // collapse the sub-properties)
        //  
        public IEnumerable SelectiveSubProperties
        {
            get {
                if (!_exposedSubProperties) 
                {
                    if (!this.IsExpanded) 
                    { 
                        yield break;
                    } 

                    _exposedSubProperties = true;
                }
 
                PropertyEntry parent = this.PropertyEntry;
                if (parent == null) 
                { 
                    yield break;
                } 

                foreach (ModelPropertyEntry subProperty in parent.PropertyValue.SubProperties)
                {
                    if (subProperty.IsBrowsable) 
                    {
                        yield return subProperty; 
                    } 
                }
            } 
        }

        // 
        // Gets a flag indicating whether the sub-property editor can be expanded or not. 
        // 
        public bool IsExpandable 
        { 
            get { return this.HasQuickTypes && this.CurrentQuickType != null; }
        } 

        // 
        // Gets a SelectionPath to itself.
        //  
        public SelectionPath Path
        { 
            get { return PropertySelectionPathInterpreter.Instance.ConstructSelectionPath(this.PropertyEntry); } 
        }
 
        // 
        // Gets a description of the contained property
        // to expose through automation
        //  
        public string Description
        { 
            get { 
                PropertyEntry property = this.PropertyEntry;
                if (property != null) 
                {
                    return string.Format(
                        CultureInfo.CurrentCulture,
                        Properties.Resources.PropertyEditing_SelectionStatus_Property, 
                        this.PropertyEntry.PropertyName);
                } 
 
                return string.Empty;
            } 
        }


        //  
        // Exposes the ItemsControl used to display the list of sub-properties.  UI-specific
        //  
        private ItemsControl SubPropertyListControl 
        {
            get { 
                if (_subPropertyListControl == null)
                {
                    _subPropertyListControl = VisualTreeUtils.GetNamedChild(this, "PART_SubPropertyList");
                    Fx.Assert(_subPropertyListControl != null, "UI for SubPropertyEditor changed.  Need to update SubPropertyEditor class logic."); 
                }
 
                return _subPropertyListControl; 
            }
        } 


        // Keyboard Navigation
 
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new SubPropertyEditorAutomationPeer(this); 
        }
 

        // Properties

        // PropertyEntry DP 

        // When the displayed PropertyEntry changes, make sure we update the UI and hook into the 
        // new PropertyEntry's notification mechanism 
        private static void OnPropertyEntryChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        { 
            SubPropertyEditor theThis = obj as SubPropertyEditor;
            if (theThis == null)
            {
                return; 
            }
 
            PropertyEntry oldValue = e.OldValue as PropertyEntry; 
            if (oldValue != null)
            { 
                oldValue.PropertyValue.RootValueChanged -= new EventHandler(theThis.OnPropertyValueRootValueChanged);
            }

            PropertyEntry newValue = e.NewValue as PropertyEntry; 
            if (newValue != null)
            { 
                newValue.PropertyValue.RootValueChanged += new EventHandler(theThis.OnPropertyValueRootValueChanged); 
            }
 
            theThis.RefreshVisuals();
        }

        private void OnPropertyValueRootValueChanged(object sender, EventArgs e) 
        {
            if (_ignoreInternalChanges) 
            { 
                return;
            } 

            RefreshVisuals();
        }
 

        // IsExpanded DP 
 
        private static void OnIsExpandedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        { 
            SubPropertyEditor theThis = obj as SubPropertyEditor;
            if (theThis == null)
            {
                return; 
            }
 
            bool newIsExpanded = (bool)e.NewValue; 
            PropertyEntry containedProperty = theThis.PropertyEntry;
 
            // Store the new expansion state
            if (containedProperty != null)
            {
                PropertyState state = PropertyStateContainer.Instance.GetPropertyState( 
                    ModelUtilities.GetCachedSubPropertyHierarchyPath(containedProperty));
                state.SubPropertiesExpanded = newIsExpanded; 
            } 

            // If we are expanded but we never exposed the sub-properties to anyone before, 
            // fire a signal saying that a list of sub-properties may be now available, so that
            // UI DataBindings refresh themselves
            if (newIsExpanded == true &&
                theThis._exposedSubProperties == false) 
            {
                theThis.FireSubPropertiesListChangedEvents(); 
            } 
        }
 
        // CurrentQuickType DP

        // This method gets called when the DP changes
        private static void OnCurrentQuickTypeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
        {
            SubPropertyEditor theThis = obj as SubPropertyEditor; 
            if (theThis == null) 
            {
                return; 
            }

            if (theThis._ignoreInternalChanges)
            { 
                return;
            } 
 
            theThis._quickTypeView.MoveCurrentTo(e.NewValue);
 
            theThis.ExpandSubProperties();
            theThis.FireSubPropertiesListChangedEvents();
        }
 
        // This method gets called when the CurrentItem on _quickTypeView changes
        private void OnCurrentQuickTypeChanged(object sender, EventArgs e) 
        { 
            if (_ignoreInternalChanges)
            { 
                return;
            }

            NewItemFactoryTypeModel selectedTypeModel = _quickTypeView.CurrentItem as NewItemFactoryTypeModel; 

            if (selectedTypeModel == null) 
            { 
                return;
            } 

            Fx.Assert(this.PropertyEntry != null, "PropertyEntry should not be null");
            if (this.PropertyEntry == null)
            { 
                return;
            } 
 
            bool previousValue = IgnoreInternalChanges();
            try 
            {
                this.PropertyEntry.PropertyValue.Value = selectedTypeModel.CreateInstance();
            }
            finally 
            {
                NoticeInternalChanges(previousValue); 
            } 
        }
 

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.Property == PropertyContainer.OwningPropertyContainerProperty) 
            {
 
                // A quick and dirty way to register this instance as the implementation of 
                // ISelectionBranchPoint that controls the expansion / collapse of this control
                // 
                OnOwningPropertyContainerChanged((PropertyContainer)e.OldValue, (PropertyContainer)e.NewValue);

            }
 
            base.OnPropertyChanged(e);
        } 
 
        private void OnOwningPropertyContainerChanged(PropertyContainer oldValue, PropertyContainer newValue)
        { 
            if (oldValue != null)
            {
                PropertySelection.ClearSelectionStop(oldValue);
                PropertySelection.ClearIsSelectionStopDoubleClickTarget(oldValue); 
            }
 
            if (newValue != null) 
            {
                PropertySelection.SetSelectionStop(newValue, this); 
                PropertySelection.SetIsSelectionStopDoubleClickTarget(newValue, true);
            }
        }
 

        // Visual Lookup Helpers 
 
        // 
        // Looks for and returns the specified sub-property 
        // 
        // Sub-property to look up
        // Corresponding PropertyEntry if found, null otherwise.
        internal PropertyEntry FindSubPropertyEntry(string propertyName) 
        {
            if (string.IsNullOrEmpty(propertyName)) 
            { 
                return null;
            } 

            foreach (PropertyEntry property in SelectiveSubProperties)
            {
                if (property.PropertyName.Equals(propertyName)) 
                {
                    return property; 
                } 
            }
 
            return null;
        }

        //  
        // Looks for and returns the PropertyContainer used to display
        // the specified PropertyEntry 
        //  
        // Property to look for
        // Corresponding PropertyContainer if found, null otherwise. 
        internal PropertyContainer FindSubPropertyEntryVisual(PropertyEntry property)
        {
            if (property == null)
            { 
                return null;
            } 
 
            ItemsControl subPropertyListControl = this.SubPropertyListControl;
            if (subPropertyListControl == null) 
            {
                return null;
            }
 
            return subPropertyListControl.ItemContainerGenerator.ContainerFromItem(property) as PropertyContainer;
        } 
 

        // Helpers 

        private void RefreshVisuals()
        {
            RefreshQuickTypes(); 
            RestoreIsExpandedState();
            FireVisualsChangedEvents(); 
        } 

        private void RefreshQuickTypes() 
        {
            bool previousValue = IgnoreInternalChanges();
            try
            { 
                _quickTypeCollection.Clear();
 
                PropertyEntry containedProperty = this.PropertyEntry; 
                if (containedProperty == null)
                { 
                    return;
                }

                ModelProperty property = ((ModelPropertyEntry)containedProperty).FirstModelProperty; 
                Type containerValueType = ((ModelPropertyEntryBase)containedProperty).CommonValueType;
                NewItemFactoryTypeModel selectedFactoryModel = null; 
                Type defaultItemType = GetDefaultItemType(property); 

                // Find all elligible NewItemFactoryTypes declared through metadata 
                IEnumerable factoryModels =
                    ExtensibilityAccessor.GetNewItemFactoryTypeModels(
                    property,
                    ResourceUtilities.GetDesiredTypeIconSize(this)); 

                if (factoryModels != null) 
                { 
                    foreach (NewItemFactoryTypeModel factoryModel in factoryModels)
                    { 
                        _quickTypeCollection.Add(factoryModel);

                        if (selectedFactoryModel == null)
                        { 
                            if (object.Equals(containerValueType, factoryModel.Type))
                            { 
                                selectedFactoryModel = factoryModel; 
                            }
                        } 

                        if (defaultItemType != null &&
                            object.Equals(defaultItemType, factoryModel.Type))
                        { 
                            defaultItemType = null;
                        } 
                    } 
                }
 
                //add a null value - user should always have an option to clear property value
                NewItemFactoryTypeModel nullTypeFactoryTypeModel =
                    new NewItemFactoryTypeModel(null, new NullItemFactory());
 
                // Add a default item type based on the property type (if it wasn't also added through
                // metadata) 
                if (defaultItemType != null) 
                {
                    NewItemFactoryTypeModel defaultItemFactoryTypeModel = new NewItemFactoryTypeModel(defaultItemType, new NewItemFactory()); 
                    _quickTypeCollection.Add(defaultItemFactoryTypeModel);

                    if (selectedFactoryModel == null)
                    { 
                        if (object.Equals(containerValueType, defaultItemFactoryTypeModel.Type))
                        { 
                            selectedFactoryModel = defaultItemFactoryTypeModel; 
                        }
                        else if (containerValueType == null) 
                        {
                            selectedFactoryModel = nullTypeFactoryTypeModel;
                        }
                    } 
                }
 
                _quickTypeCollection.Add(nullTypeFactoryTypeModel); 

                // Make sure the currently selected value on the CollectionView reflects the 
                // actual value of the property
                _quickTypeView.MoveCurrentTo(selectedFactoryModel);
                this.CurrentQuickType = selectedFactoryModel;
            } 
            finally
            { 
                NoticeInternalChanges(previousValue); 
            }
        } 

        private static Type GetDefaultItemType(ModelProperty property)
        {
            if (property == null) 
            {
                return null; 
            } 

            Type propertyType = property.PropertyType; 
            if (EditorUtilities.IsConcreteWithDefaultCtor(propertyType))
            {
                return propertyType;
            } 

            return null; 
        } 

        private void RestoreIsExpandedState() 
        {
            bool newIsExpanded = false;
            PropertyEntry property = this.PropertyEntry;
 
            if (property != null)
            { 
                PropertyState state = PropertyStateContainer.Instance.GetPropertyState( 
                    ModelUtilities.GetCachedSubPropertyHierarchyPath(property));
                newIsExpanded = state.SubPropertiesExpanded; 
            }

            this.IsExpanded = newIsExpanded;
            _exposedSubProperties = false; 
        }
 
        private void ExpandSubProperties() 
        {
            this.IsExpanded = true; 
        }


        // Change Notification Helpers 

        private bool IgnoreInternalChanges() 
        { 
            bool previousValue = _ignoreInternalChanges;
            _ignoreInternalChanges = true; 
            return previousValue;
        }

        private void NoticeInternalChanges(bool previousValue) 
        {
            _ignoreInternalChanges = previousValue; 
        } 

        private void FireVisualsChangedEvents() 
        {
            // Fire updated events
            OnPropertyChanged("HasQuickTypes");
            OnPropertyChanged("QuickTypes"); 
            FireSubPropertiesListChangedEvents();
        } 
 
        private void FireSubPropertiesListChangedEvents()
        { 
            OnPropertyChanged("IsExpandable");
            OnPropertyChanged("SelectiveSubProperties");

            if (VisualsChanged != null) 
            {
                VisualsChanged(this, EventArgs.Empty); 
            } 
        }
 

        // INotifyPropertyChanged Members

        private void OnPropertyChanged(string propertyName) 
        {
            Fx.Assert(!string.IsNullOrEmpty(propertyName), "Can't raise OnPropertyChanged event without a valid property name."); 
 
            if (PropertyChanged != null)
            { 
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
 
        // ISelectionStop Members
 
        //NullItemFactory - this class is used to provide a null entry in quick types list - it is required to allow user 
        //to clear value of an object.
        sealed class NullItemFactory : NewItemFactory 
        {
            public override object CreateInstance(Type type)
            {
                //no input type is allowed - we never create instance of anything 
                Fx.Assert(type == null, "NullItemFactory supports only null as type parameter");
                return null; 
            } 

            public override string GetDisplayName(Type type) 
            {
                //no input type is allowed - we always return (null) string
                Fx.Assert(type == null, "NullItemFactory supports only null as type parameter");
                return "(null)"; 
            }
        } 
    } 
}

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

10818,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Editors/RTLValueConverter.cs/1305376/RTLValueConverter.cs,4/26/2010 8:54:39 AM,2638
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.Internal.PropertyEditing.Editors
{ 

    using System; 
    using System.Collections; 
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows;
    using System.Activities.Presentation.Internal.PropertyEditing.Model; 
    using System.Activities.Presentation.Internal.PropertyEditing.Resources;
    using System.Activities.Presentation.PropertyEditing; 
    using System.Activities.Presentation; 
    using System.Runtime;
 
    // 
    // Checks the property entry and converts it
    // to appropriate FlowDirection value which is returned back.
    //  
    [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
    internal class RTLValueConveter : IMultiValueConverter 
    { 
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
            FlowDirection returnValue = FlowDirection.LeftToRight; 
            Fx.Assert(values.Length == 3, "Incorrect values in the MultiValueConverter!");
            if (values.Length == 3)
            {
                ModelPropertyEntry propertyEntry = values[1] as ModelPropertyEntry; 
                if (propertyEntry != null)
                { 
                    if (!propertyEntry.DisplayName.Equals("Name")) 
                    {
                        if (targetType == typeof(FlowDirection)) 
                        {
                            object propertyValue = values[0];
                            if (propertyValue == null || propertyValue.GetType() == typeof(string))
                            { 
                                //customize it to controls FlowDirection Property
                                returnValue = (FlowDirection)PropertyInspectorResources.GetResources()["SelectedControlFlowDirectionRTL"]; 
                            } 
                        }
                    } 
                }
            }
            return returnValue;
        } 

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

    }
}

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

10819,/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/cdf/src/NetFx40/Tools/System.Activities.Presentation/System/Activities/Presentation/Base/Core/Internal/PropertyEditing/Editors/FlagStringConverter.cs/1305376/FlagStringConverter.cs,4/26/2010 8:54:39 AM,3013
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.Activities.Presentation.Internal.PropertyEditing.Editors 
{
    using System.Windows.Data; 
    using System.Globalization; 
    using System.Collections.Generic;
    using System.Runtime; 
    using System.Collections;
    sealed class FlagStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
        {
            if (value != null) 
            { 
                return value.ToString();
            } 
            else
            {
                return string.Empty;
            } 
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
        {
            Type flagType = parameter as Type; 
            Fx.Assert(flagType != null && flagType.IsEnum, "TargetType should be enum");
            Fx.Assert(Attribute.IsDefined(flagType, typeof(FlagsAttribute)), "FlagType should have flags attribute");

            if (value == null) 
            {
                return Enum.ToObject(flagType, 0); 
            } 

            string str = (value as string).ToUpperInvariant(); 
            str = str.Trim();
            if (str.Equals(string.Empty) || str.Equals("0"))
            {
                return Enum.ToObject(flagType, 0); 
            }
 
            Dictionary flagDictionary = GenerateFlagDictionary(flagType); 
            int flagsIntValue = 0;
            string[] names = str.Split(','); 
            foreach (string name in names)
            {
                string flagName = name.Trim();
                if (flagDictionary.ContainsKey(flagName)) 
                {
                    flagsIntValue |= (int)flagDictionary[flagName]; 
                    flagDictionary.Remove(flagName); 
                }
                else 
                {
                    throw FxTrace.Exception.AsError(new ArgumentException(string.Format(CultureInfo.CurrentUICulture, SR.InvalidFlagName, value, flagType.Name)));
                }
            } 
            return Enum.ToObject(flagType, flagsIntValue);
        } 
 
        static Dictionary GenerateFlagDictionary(Type flagType)
        { 
            Dictionary flagDictionary = new Dictionary();
            string[] flagNames = flagType.GetEnumNames();
            Array flagValues = flagType.GetEnumValues();
            for (int i = 0; i < flagNames.Length; i++) 
            {
                flagDictionary.Add(flagNames[i].ToUpperInvariant(), flagValues.GetValue(i)); 
            } 
            return flagDictionary;
        } 
    }
}

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


                        

Link Menu

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