WorkflowItemsPresenter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

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

namespace System.Activities.Presentation 
{
    using System.Activities.Presentation.Internal.PropertyEditing; 
    using System.Activities.Presentation.Model; 
    using System.Activities.Presentation.Services;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq; 
    using System.Runtime;
    using System.Windows; 
    using System.Windows.Automation.Peers; 
    using System.Windows.Controls;
    using System.Windows.Input; 
    using System.Windows.Markup;
    using System.Windows.Media;
    using System.Windows.Threading;
    using System.Activities.Presentation.View; 
    using System.Windows.Shapes;
 
 
    // This is similar to the WorkflowItemPresenter , but its an edit box for collections. It supports drag drop, and delete.
    // it auto refreshes the collection on collection changed events. 
    public class WorkflowItemsPresenter : ContentControl, ICompositeView
    {

        public static readonly DependencyProperty HintTextProperty = 
            DependencyProperty.Register("HintText", typeof(string), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(String.Empty, new PropertyChangedCallback(WorkflowItemsPresenter.OnHintTextChanged)));
 
        public static readonly DependencyProperty ItemsProperty = 
            DependencyProperty.Register("Items", typeof(ModelItemCollection), typeof(WorkflowItemsPresenter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(WorkflowItemsPresenter.OnItemsChanged)));
 
        public static readonly DependencyProperty SpacerTemplateProperty =
            DependencyProperty.Register("SpacerTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));

        public static readonly DependencyProperty HeaderTemplateProperty = 
            DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));
 
        public static readonly DependencyProperty FooterTemplateProperty = 
            DependencyProperty.Register("FooterTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));
 
        public static readonly DependencyProperty ItemsPanelProperty =
            DependencyProperty.Register("ItemsPanel", typeof(ItemsPanelTemplate), typeof(WorkflowItemsPresenter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(WorkflowItemsPresenter.OnItemsPanelChanged)));

        public static readonly DependencyProperty IndexProperty = 
            DependencyProperty.RegisterAttached("Index", typeof(int), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(addAtEndMarker));
 
        public static readonly DependencyProperty AllowedItemTypeProperty = 
            DependencyProperty.Register("AllowedItemType", typeof(Type), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(typeof(object)));
 
        public static readonly DependencyProperty IsDefaultContainerProperty =
            DependencyProperty.Register("IsDefaultContainer", typeof(bool), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(false));

        public static readonly DependencyProperty DroppingTypeResolvingOptionsProperty = 
            DependencyProperty.Register("DroppingTypeResolvingOptions", typeof(TypeResolvingOptions), typeof(WorkflowItemsPresenter));
 
 
        const int addAtEndMarker = -2;
 
        int selectedSpacerIndex;


        ItemsControl panel; 
        Grid hintTextGrid;
        EditingContext context = null; 
        bool isRegisteredWithParent = false; 
        bool populateOnLoad = false;
        bool handleSpacerGotKeyboardFocus = false; 
        Grid outerGrid;

        public WorkflowItemsPresenter()
        { 
            panel = new ItemsControl();
            panel.Focusable = false; 
            hintTextGrid = new Grid(); 
            hintTextGrid.Focusable = false;
            hintTextGrid.Background = Brushes.Transparent; 
            hintTextGrid.DataContext = this;
            hintTextGrid.SetBinding(Grid.MinHeightProperty, "MinHeight");
            hintTextGrid.SetBinding(Grid.MinWidthProperty, "MinWidth");
            TextBlock text = new TextBlock(); 
            text.Focusable = false;
            text.SetBinding(TextBlock.TextProperty, "HintText"); 
            text.HorizontalAlignment = HorizontalAlignment.Center; 
            text.VerticalAlignment = VerticalAlignment.Center;
            text.DataContext = this; 
            text.Foreground = new SolidColorBrush(SystemColors.GrayTextColor);
            text.FontStyle = FontStyles.Italic;
            ((IAddChild)hintTextGrid).AddChild(text);
 
            this.outerGrid = new Grid()
            { 
                RowDefinitions = { new RowDefinition(), new RowDefinition() }, 
                ColumnDefinitions = { new ColumnDefinition() }
            }; 
            Grid.SetRow(this.panel, 0);
            Grid.SetColumn(this.panel, 0);
            Grid.SetRow(this.hintTextGrid, 1);
            Grid.SetColumn(this.hintTextGrid, 0); 
            this.outerGrid.Children.Add(panel);
            this.outerGrid.Children.Add(hintTextGrid); 
        } 

 
        public Type AllowedItemType
        {
            get { return (Type)GetValue(AllowedItemTypeProperty); }
            set { SetValue(AllowedItemTypeProperty, value); } 
        }
 
        public string HintText 
        {
            get { return (string)GetValue(HintTextProperty); } 
            set { SetValue(HintTextProperty, value); }
        }

        [Fx.Tag.KnownXamlExternal] 
        public DataTemplate SpacerTemplate
        { 
            get { return (DataTemplate)GetValue(SpacerTemplateProperty); } 
            set { SetValue(SpacerTemplateProperty, value); }
        } 

        [Fx.Tag.KnownXamlExternal]
        public DataTemplate HeaderTemplate
        { 
            get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
            set { SetValue(HeaderTemplateProperty, value); } 
        } 

        [Fx.Tag.KnownXamlExternal] 
        public DataTemplate FooterTemplate
        {
            get { return (DataTemplate)GetValue(FooterTemplateProperty); }
            set { SetValue(FooterTemplateProperty, value); } 
        }
 
        [Fx.Tag.KnownXamlExternal] 
        public ItemsPanelTemplate ItemsPanel
        { 
            get { return (ItemsPanelTemplate)GetValue(ItemsPanelProperty); }
            set { SetValue(ItemsPanelProperty, value); }
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.CollectionPropertiesShouldBeReadOnly,
            Justification = "Setter is provided to enable setting this property in code.")] 
        [Fx.Tag.KnownXamlExternal] 
        public ModelItemCollection Items
        { 
            get { return (ModelItemCollection)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }
 
        EditingContext Context
        { 
            get 
            {
                if (context == null) 
                {
                    IModelTreeItem modelTreeItem = this.Items as IModelTreeItem;
                    if (modelTreeItem != null)
                    { 
                        this.context = modelTreeItem.ModelTreeManager.Context;
                    } 
                } 
                return context;
            } 
        }

        public bool IsDefaultContainer
        { 
            get { return (bool)GetValue(IsDefaultContainerProperty); }
            set { SetValue(IsDefaultContainerProperty, value); } 
        } 

        [Fx.Tag.KnownXamlExternal] 
        public TypeResolvingOptions DroppingTypeResolvingOptions
        {
            get { return (TypeResolvingOptions)GetValue(DroppingTypeResolvingOptionsProperty); }
            set { SetValue(DroppingTypeResolvingOptionsProperty, value); } 
        }
 
        static void OnHintTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject; 
            itemsPresenter.UpdateHintTextVisibility(e.NewValue as string);
        }

        static void OnItemsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject; 
            itemsPresenter.OnItemsChanged(e.NewValue); 
        }
 
        static void OnItemsPanelChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject;
            itemsPresenter.panel.ItemsPanel = (ItemsPanelTemplate)e.NewValue; 
        }
 
        void OnItemsChanged(object newItems) 
        {
            ModelItemCollection newItemsCollection = (ModelItemCollection)newItems; 
            if (!isRegisteredWithParent)
            {
                CutCopyPasteHelper.RegisterWithParentViewElement(this);
                isRegisteredWithParent = true; 
            }
            populateOnLoad = false; 
            PopulateContent(); 
        }
 
        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // if this.Items is null, and we are getting a collection changed that
            // means this event some how happened before this can get the unloaded event 
            // and unsubscribe from this event.
            if (this.Items == null) 
            { 
                return;
            } 
            bool fullRepopulateNeeded = true;

            // when one item is dropped into this items presenter focus on the new view element for it.
            if (e.Action == NotifyCollectionChangedAction.Add 
                && e.NewItems != null
                && e.NewItems.Count == 1) 
            { 
                // insert itemview and spacer
                fullRepopulateNeeded = false; 
                int itemViewIndex = GetViewIndexForItem(e.NewStartingIndex);
                VirtualizedContainerService containerService = this.Context.Services.GetService();
                UIElement itemView = containerService.GetContainer((ModelItem)e.NewItems[0], this);
                this.panel.Items.Insert(itemViewIndex, itemView as UIElement); 
                // index 2 + i*2 + 1 is spacer i+1
                FrameworkElement spacer = CreateSpacer(); 
                this.panel.Items.Insert(itemViewIndex + 1, spacer); 

 
                ModelItem insertedItem = (ModelItem)e.NewItems[0];
                this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() =>
                {
                    UIElement view = (UIElement)insertedItem.View; 
                    if (view != null)
                    { 
                        Keyboard.Focus(view); 
                    }
                })); 
            }

            else if (e.Action == NotifyCollectionChangedAction.Remove)
            { 
                if (e.OldItems != null && e.OldItems.Count == 1)
                { 
                    fullRepopulateNeeded = false; 
                    int itemViewIndex = GetViewIndexForItem(e.OldStartingIndex);
                    this.panel.Items.RemoveAt(itemViewIndex); 
                    //remove spacer also
                    this.panel.Items.RemoveAt(itemViewIndex);
                }
 
                if (this.Items.Count == 0)
                { 
                    fullRepopulateNeeded = true; 
                }
 
                // deselect removed items
                if (this.Context != null)
                {
                    IList selectedItems = this.Context.Items.GetValue().SelectedObjects.ToList(); 
                    foreach (ModelItem selectedAndRemovedItem in selectedItems.Intersect(e.OldItems.Cast()))
                    { 
                        Selection.Toggle(this.Context, selectedAndRemovedItem); 
                    }
                } 
            }
            if (this.Items.Count > 0)
            {
                this.hintTextGrid.Visibility = Visibility.Collapsed; 
            }
            else 
            { 
                this.hintTextGrid.Visibility = Visibility.Visible;
            } 

            if (fullRepopulateNeeded)
            {
                PopulateContent(); 
            }
        } 
 
        protected override void OnInitialized(EventArgs e)
        { 
            base.OnInitialized(e);
            this.AllowDrop = true;
            this.Content = outerGrid;
            if (this.ItemsPanel != null) 
            {
                this.panel.ItemsPanel = this.ItemsPanel; 
            } 

            ICompositeViewEvents containerEvents = null; 
            bool isDefault = false;

            this.Loaded += (s, eventArgs) =>
            { 
                isDefault = this.IsDefaultContainer;
                selectedSpacerIndex = addAtEndMarker; 
                DependencyObject parent = VisualTreeHelper.GetParent(this); 
                while (null != parent && !typeof(ICompositeViewEvents).IsAssignableFrom(parent.GetType()))
                { 
                    parent = VisualTreeHelper.GetParent(parent);
                }
                containerEvents = parent as ICompositeViewEvents;
                if (null != containerEvents) 
                {
                    if (isDefault) 
                    { 
                        containerEvents.RegisterDefaultCompositeView(this);
                    } 
                    else
                    {
                        containerEvents.RegisterCompositeView(this);
                    } 
                }
                if (this.Items != null) 
                { 
                    //UnRegistering because of 137896: Inside tab control multiple Loaded events happen without an Unloaded event.
                    this.Items.CollectionChanged -= new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
                    this.Items.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
                }
                if (populateOnLoad)
                { 
                    this.PopulateContent();
                } 
            }; 

            this.Unloaded += (s, eventArgs) => 
            {
                if (null != containerEvents)
                {
                    if (isDefault) 
                    {
                        containerEvents.UnregisterDefaultCompositeView(this); 
                    } 
                    else
                    { 
                        containerEvents.UnregisterCompositeView(this);

                    }
                } 
                if (this.Items != null)
                { 
                    this.Items.CollectionChanged -= new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
                }
                populateOnLoad = true; 
            };
        }

        void PopulateContent() 
        {
            this.panel.Items.Clear(); 
 
            if (this.Items != null)
            { 

                // index 0 is header.
                ContentControl header = new ContentControl();
                header.Focusable = false; 
                header.ContentTemplate = this.HeaderTemplate;
                header.SetValue(IndexProperty, 0); 
                header.Drop += new DragEventHandler(OnSpacerDrop); 
                this.panel.Items.Add(header);
 
                // index 1 is first spacer
                FrameworkElement startSpacer = CreateSpacer();
                this.panel.Items.Add(startSpacer);
 
                foreach (ModelItem item in this.Items)
                { 
                    // index 2 + i*2 is itemView i 
                    VirtualizedContainerService containerService = this.Context.Services.GetService();
                    UIElement itemView = containerService.GetContainer(item, this); 
                    this.panel.Items.Add(itemView as UIElement);
                    // index 2 + i*2 + 1 is spacer i+1
                    FrameworkElement spacer = CreateSpacer();
                    this.panel.Items.Add(spacer); 
                }
                // index 2 + count*2 is footer 
                ContentControl footer = new ContentControl(); 
                footer.ContentTemplate = this.FooterTemplate;
                footer.Focusable = true; 
                footer.IsHitTestVisible = true;
                footer.IsTabStop = true;
                footer.SetValue(IndexProperty, addAtEndMarker);
                footer.Drop += new DragEventHandler(OnSpacerDrop); 
                footer.LostFocus += new RoutedEventHandler(OnSpacerLostFocus);
                footer.GotFocus += new RoutedEventHandler(OnSpacerGotFocus); 
                this.panel.Items.Add(footer); 
                footer.Focusable = false;
            } 
            UpdateHintTextVisibility(HintText);
        }

        int GetViewIndexForItem(int itemIndex) 
        {
            return 2 + itemIndex * 2; 
        } 

        int GetViewIndexForSpacer(int spacerIndex) 
        {
            return 2 + spacerIndex * 2 + 1;
        }
 
        int GetSpacerIndex(int viewIndex)
        { 
            if (viewIndex == 1) 
            {
                return 0; 
            }
            else
            {
                return (viewIndex - 3) / 2 + 1; 
            }
        } 
 
        void UpdateHintTextVisibility(string hintText)
        { 
            if (this.hintTextGrid != null && this.Items != null)
            {
                this.hintTextGrid.Visibility = (this.Items.Count == 0 && !string.IsNullOrEmpty(hintText)) ? Visibility.Visible : Visibility.Collapsed;
            } 
        }
 
        private FrameworkElement CreateSpacer() 
        {
            FrameworkElement spacer = (this.SpacerTemplate != null) ? (FrameworkElement)this.SpacerTemplate.LoadContent() : new Rectangle(); 
            spacer.IsHitTestVisible = true;
            Control spacerControl = spacer as Control;
            if (spacerControl != null)
            { 
                spacerControl.IsTabStop = true;
            } 
            spacer.Drop += new DragEventHandler(OnSpacerDrop); 
            spacer.LostFocus += new RoutedEventHandler(OnSpacerLostFocus);
            spacer.GotFocus += new RoutedEventHandler(OnSpacerGotFocus); 
            spacer.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(OnSpacerGotKeyboardFocus);
            spacer.MouseDown += new MouseButtonEventHandler(OnSpacerMouseDown);
            return spacer;
        } 

        void OnSpacerDrop(object sender, DragEventArgs e) 
        { 
            int index = GetSpacerIndexFromView(sender);
            OnItemDropped(e, index); 
        }

        private int GetSpacerIndexFromView(object sender)
        { 
            if (((DependencyObject)sender).ReadLocalValue(IndexProperty) != DependencyProperty.UnsetValue)
            { 
                int index = (int)((DependencyObject)sender).GetValue(IndexProperty); 
                return index;
            } 
            else
            {
                return GetSpacerIndex(this.panel.Items.IndexOf(sender));
            } 
        }
 
        void OnSpacerGotFocus(object sender, RoutedEventArgs e) 
        {
            int index = GetSpacerIndexFromView(sender); 
            selectedSpacerIndex = index;
        }

        void OnSpacerGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
        {
            // Handle the event so that it won't be routed to the containing designer to affect selection 
            if (handleSpacerGotKeyboardFocus) 
            {
                e.Handled = true; 
            }
        }

        void OnSpacerLostFocus(object sender, RoutedEventArgs e) 
        {
            int index = GetSpacerIndexFromView(sender); 
            selectedSpacerIndex = addAtEndMarker; 
        }
 
        void OnSpacerMouseDown(object sender, MouseButtonEventArgs e)
        {
            // Schedule the Keyboard.Focus command to let it execute later than WorkflowViewElement.OnMouseDown
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => 
            {
                this.handleSpacerGotKeyboardFocus = true; 
                Keyboard.Focus((FrameworkElement)sender); 
                this.handleSpacerGotKeyboardFocus = false;
            })); 
        }

        void OnItemDropped(DragEventArgs e, int index)
        { 
            DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.None);
            object droppedObject = DragDropHelper.GetDroppedObject(this, e, Context); 
            ICompositeView sourceContainer = DragDropHelper.GetCompositeView(e); 
            if (droppedObject != null)
            { 
                // move within this presenter case, dont set anything in e.Effects.
                // this just causes an change in ordering within the collection
                if (sourceContainer == this)
                { 
                    Fx.Assert(this.Items.Contains(droppedObject), "droppedObject should have been added to the Items collection");
                    int oldIndex; 
                    if (droppedObject is ModelItem) 
                    {
                        oldIndex = this.Items.IndexOf((ModelItem)droppedObject); 
                    }
                    else
                    {
                        oldIndex = ((IList)this.Items.GetCurrentValue()).IndexOf(droppedObject); 
                    }
                    // this check excludes the case where an item is dropped on to the spacer just before or just after itself. 
                    if (index != oldIndex && index != (oldIndex + 1)) 
                    {
                        //if element is placed ahead of old location, decrement the index not to include moved object 
                        if (oldIndex < index)
                        {
                            --index;
                        } 
                        this.Items.Remove(droppedObject);
                        InsertItem(index, droppedObject); 
                    } 
                }
                // dropped from elsewhere case, consider it a move. 
                else
                {
                    if (IsDropAllowed(droppedObject))
                    { 
                        InsertItem(index, droppedObject);
                        DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move); 
                    } 
                }
                e.Handled = true; 
            }

        }
 
        private bool IsDropAllowed(object droppedObject)
        { 
            bool isDropAllowed = false; 
            ModelItem modelItem = droppedObject as ModelItem;
            if (modelItem != null && !IsInParentChain(modelItem)) 
            {
                if (this.AllowedItemType.IsAssignableFrom(modelItem.ItemType))
                {
                    isDropAllowed = true; 
                }
            } 
            else if (droppedObject is Type && this.AllowedItemType.IsAssignableFrom((Type)droppedObject)) 
            {
                isDropAllowed = true; 
            }
            else
            {
                if (this.AllowedItemType.IsAssignableFrom(droppedObject.GetType())) 
                {
                    isDropAllowed = true; 
                } 
            }
            return isDropAllowed; 
        }

        private bool IsInParentChain(ModelItem droppedModelItem)
        { 
            bool isInParentChain = false;
            ModelItem parentModelItem = this.Items; 
            while (parentModelItem != null) 
            {
                if (parentModelItem == droppedModelItem) 
                {
                    isInParentChain = true;
                    break;
                } 
                parentModelItem = parentModelItem.Parent;
            } 
            return isInParentChain; 
        }
 
        void InsertItem(int index, object droppedObject)
        {
            ModelItem insertedItem = null;
            if (index == addAtEndMarker || index >= this.Items.Count) 
            {
                insertedItem = this.Items.Add(droppedObject); 
            } 
            else
            { 
                insertedItem = this.Items.Insert(index, droppedObject);
            }
            if (insertedItem != null)
            { 
                Selection.SelectOnly(this.Context, insertedItem);
            } 
        } 

        protected override void OnDrop(DragEventArgs e) 
        {
            int index = addAtEndMarker;
            WorkflowViewElement dropTarget = null;
            if (e.OriginalSource is WorkflowViewElement) 
            {
                dropTarget = (WorkflowViewElement)e.OriginalSource; 
            } 
            else
            { 
                dropTarget = VisualTreeUtils.FindFocusableParent((UIElement)e.OriginalSource);
            }

            if (null != dropTarget && null != dropTarget.ModelItem) 
            {
                int targetIndex = this.Items.IndexOf(dropTarget.ModelItem); 
                if (-1 != targetIndex) 
                {
                    index = targetIndex + 1; 
                }
            }
            OnItemDropped(e, index);
            base.OnDrop(e); 
        }
 
        void OnDrag(DragEventArgs e) 
        {
            if (!e.Handled) 
            {
                if (!DragDropHelper.AllowDrop(e.Data, this.Context, this.AllowedItemType))
                {
                    e.Effects = DragDropEffects.None; 
                }
                e.Handled = true; 
            } 
        }
 
        protected override void OnDragEnter(DragEventArgs e)
        {
            this.OnDrag(e);
            base.OnDragEnter(e); 
        }
 
        protected override void OnDragOver(DragEventArgs e) 
        {
            this.OnDrag(e); 
            base.OnDragOver(e);
        }

 
        public void OnItemMoved(ModelItem modelItem)
        { 
            if (this.Items.Contains(modelItem)) 
            {
                this.Items.Remove(modelItem); 
            }
        }

        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new WorkflowItemsPresenterAutomationPeer(this); 
        } 

        public object OnItemsCut(List itemsToCut) 
        {
            List orderMetaData = GetOrderMetaData(itemsToCut).ToList();
            foreach (ModelItem item in itemsToCut)
            { 
                this.Items.Remove(item);
                this.Context.Items.SetValue(new Selection(new ArrayList())); 
            } 
            return orderMetaData;
        } 

        public object OnItemsCopied(List itemsToCopy)
        {
            return GetOrderMetaData(itemsToCopy).ToList(); 
        }
 
        IList GetOrderMetaData(IList itemsToCopy) 
        {
            SortedList orderedList = new SortedList(); 
            foreach (ModelItem modelItem in itemsToCopy)
            {
                int index = this.Items.IndexOf(modelItem);
                if (index > -1) 
                {
                    orderedList.Add(index, modelItem.GetCurrentValue()); 
                } 
            }
            return orderedList.Values; 
        }

        public void OnItemsPasted(List itemsToPaste, List metaData, Point pastePoint, WorkflowViewElement pastePointReference)
        { 
            // first see if a spacer is selected.
            int index = this.selectedSpacerIndex; 
            // else see if we can paste after a selected child 
            if (index < 0)
            { 
                Selection currentSelection = this.Context.Items.GetValue();
                index = this.Items.IndexOf(currentSelection.PrimarySelection);
                //paste after the selected child
                if (index >= 0) 
                {
                    index++; 
                } 
            }
            if (index < 0) 
            {
                index = addAtEndMarker;
            }
 
            List mergedItemsToPaste = new List();
            if (metaData != null) 
            { 
                foreach (object metaDataObject in metaData)
                { 
                    List orderedItemsMetaData = metaDataObject as List;
                    if (orderedItemsMetaData != null)
                    {
                        foreach (object objectToPaste in orderedItemsMetaData) 
                        {
                            if (!mergedItemsToPaste.Contains(objectToPaste)) 
                            { 
                                mergedItemsToPaste.Add(objectToPaste);
                            } 
                        }
                    }
                }
            } 

            foreach (object itemToPaste in itemsToPaste) 
            { 
                if (!mergedItemsToPaste.Contains(itemToPaste))
                { 
                    mergedItemsToPaste.Add(itemToPaste);
                }
            }
 
            List modelItemsToSelect = new List();
 
            foreach (object itemToPaste in mergedItemsToPaste) 
            {
                if (IsDropAllowed(itemToPaste)) 
                {
                    if (index == addAtEndMarker)
                    {
                        modelItemsToSelect.Add(this.Items.Add(itemToPaste)); 
                    }
                    else 
                    { 
                        modelItemsToSelect.Add(this.Items.Insert(index, itemToPaste));
                    } 
                    if (index >= 0)
                    {
                        index++;
                    } 
                }
            } 
 
            this.Context.Items.SetValue(new Selection(modelItemsToSelect));
        } 

        public void OnItemsDelete(List itemsToDelete)
        {
            if (null != itemsToDelete) 
            {
                itemsToDelete.ForEach(p => 
                { 
                    if (null != this.Items && this.Items.Contains(p))
                    { 
                        this.Items.Remove(p);
                    }
                }
                    ); 
            }
        } 
 
        public bool CanPasteItems(List itemsToPaste)
        { 
            bool result = false;
            if (null != itemsToPaste && itemsToPaste.Count > 0)
            {
                result = itemsToPaste.All(p => this.IsDropAllowed(p)); 
            }
            return result; 
        } 

        class WorkflowItemsPresenterAutomationPeer : UIElementAutomationPeer 
        {
            WorkflowItemsPresenter owner;

            public WorkflowItemsPresenterAutomationPeer(WorkflowItemsPresenter owner) 
                : base(owner)
            { 
                this.owner = owner; 
            }
 
            protected override AutomationControlType GetAutomationControlTypeCore()
            {
                return AutomationControlType.Custom;
            } 

            protected override string GetAutomationIdCore() 
            { 
                string automationId = base.GetAutomationIdCore();
                if (string.IsNullOrEmpty(automationId)) 
                {
                    automationId = base.GetNameCore();
                    if (string.IsNullOrEmpty(automationId))
                    { 
                        automationId = this.owner.GetType().Name;
                    } 
                } 
                return automationId;
            } 

            protected override string GetNameCore()
            {
                // Return an empty string if some activites are dropped on the presenter 
                if (owner.Items.Count > 0)
                { 
                    return string.Empty; 
                }
                string name = base.GetNameCore(); 
                if (string.IsNullOrEmpty(name))
                {
                    name = this.owner.HintText;
                } 
                return name;
            } 
 
            protected override string GetClassNameCore()
            { 
                return this.owner.GetType().Name;
            }
        }
 
    }
} 

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

namespace System.Activities.Presentation 
{
    using System.Activities.Presentation.Internal.PropertyEditing; 
    using System.Activities.Presentation.Model; 
    using System.Activities.Presentation.Services;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq; 
    using System.Runtime;
    using System.Windows; 
    using System.Windows.Automation.Peers; 
    using System.Windows.Controls;
    using System.Windows.Input; 
    using System.Windows.Markup;
    using System.Windows.Media;
    using System.Windows.Threading;
    using System.Activities.Presentation.View; 
    using System.Windows.Shapes;
 
 
    // This is similar to the WorkflowItemPresenter , but its an edit box for collections. It supports drag drop, and delete.
    // it auto refreshes the collection on collection changed events. 
    public class WorkflowItemsPresenter : ContentControl, ICompositeView
    {

        public static readonly DependencyProperty HintTextProperty = 
            DependencyProperty.Register("HintText", typeof(string), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(String.Empty, new PropertyChangedCallback(WorkflowItemsPresenter.OnHintTextChanged)));
 
        public static readonly DependencyProperty ItemsProperty = 
            DependencyProperty.Register("Items", typeof(ModelItemCollection), typeof(WorkflowItemsPresenter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(WorkflowItemsPresenter.OnItemsChanged)));
 
        public static readonly DependencyProperty SpacerTemplateProperty =
            DependencyProperty.Register("SpacerTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));

        public static readonly DependencyProperty HeaderTemplateProperty = 
            DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));
 
        public static readonly DependencyProperty FooterTemplateProperty = 
            DependencyProperty.Register("FooterTemplate", typeof(DataTemplate), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(null));
 
        public static readonly DependencyProperty ItemsPanelProperty =
            DependencyProperty.Register("ItemsPanel", typeof(ItemsPanelTemplate), typeof(WorkflowItemsPresenter), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(WorkflowItemsPresenter.OnItemsPanelChanged)));

        public static readonly DependencyProperty IndexProperty = 
            DependencyProperty.RegisterAttached("Index", typeof(int), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(addAtEndMarker));
 
        public static readonly DependencyProperty AllowedItemTypeProperty = 
            DependencyProperty.Register("AllowedItemType", typeof(Type), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(typeof(object)));
 
        public static readonly DependencyProperty IsDefaultContainerProperty =
            DependencyProperty.Register("IsDefaultContainer", typeof(bool), typeof(WorkflowItemsPresenter), new UIPropertyMetadata(false));

        public static readonly DependencyProperty DroppingTypeResolvingOptionsProperty = 
            DependencyProperty.Register("DroppingTypeResolvingOptions", typeof(TypeResolvingOptions), typeof(WorkflowItemsPresenter));
 
 
        const int addAtEndMarker = -2;
 
        int selectedSpacerIndex;


        ItemsControl panel; 
        Grid hintTextGrid;
        EditingContext context = null; 
        bool isRegisteredWithParent = false; 
        bool populateOnLoad = false;
        bool handleSpacerGotKeyboardFocus = false; 
        Grid outerGrid;

        public WorkflowItemsPresenter()
        { 
            panel = new ItemsControl();
            panel.Focusable = false; 
            hintTextGrid = new Grid(); 
            hintTextGrid.Focusable = false;
            hintTextGrid.Background = Brushes.Transparent; 
            hintTextGrid.DataContext = this;
            hintTextGrid.SetBinding(Grid.MinHeightProperty, "MinHeight");
            hintTextGrid.SetBinding(Grid.MinWidthProperty, "MinWidth");
            TextBlock text = new TextBlock(); 
            text.Focusable = false;
            text.SetBinding(TextBlock.TextProperty, "HintText"); 
            text.HorizontalAlignment = HorizontalAlignment.Center; 
            text.VerticalAlignment = VerticalAlignment.Center;
            text.DataContext = this; 
            text.Foreground = new SolidColorBrush(SystemColors.GrayTextColor);
            text.FontStyle = FontStyles.Italic;
            ((IAddChild)hintTextGrid).AddChild(text);
 
            this.outerGrid = new Grid()
            { 
                RowDefinitions = { new RowDefinition(), new RowDefinition() }, 
                ColumnDefinitions = { new ColumnDefinition() }
            }; 
            Grid.SetRow(this.panel, 0);
            Grid.SetColumn(this.panel, 0);
            Grid.SetRow(this.hintTextGrid, 1);
            Grid.SetColumn(this.hintTextGrid, 0); 
            this.outerGrid.Children.Add(panel);
            this.outerGrid.Children.Add(hintTextGrid); 
        } 

 
        public Type AllowedItemType
        {
            get { return (Type)GetValue(AllowedItemTypeProperty); }
            set { SetValue(AllowedItemTypeProperty, value); } 
        }
 
        public string HintText 
        {
            get { return (string)GetValue(HintTextProperty); } 
            set { SetValue(HintTextProperty, value); }
        }

        [Fx.Tag.KnownXamlExternal] 
        public DataTemplate SpacerTemplate
        { 
            get { return (DataTemplate)GetValue(SpacerTemplateProperty); } 
            set { SetValue(SpacerTemplateProperty, value); }
        } 

        [Fx.Tag.KnownXamlExternal]
        public DataTemplate HeaderTemplate
        { 
            get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
            set { SetValue(HeaderTemplateProperty, value); } 
        } 

        [Fx.Tag.KnownXamlExternal] 
        public DataTemplate FooterTemplate
        {
            get { return (DataTemplate)GetValue(FooterTemplateProperty); }
            set { SetValue(FooterTemplateProperty, value); } 
        }
 
        [Fx.Tag.KnownXamlExternal] 
        public ItemsPanelTemplate ItemsPanel
        { 
            get { return (ItemsPanelTemplate)GetValue(ItemsPanelProperty); }
            set { SetValue(ItemsPanelProperty, value); }
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.CollectionPropertiesShouldBeReadOnly,
            Justification = "Setter is provided to enable setting this property in code.")] 
        [Fx.Tag.KnownXamlExternal] 
        public ModelItemCollection Items
        { 
            get { return (ModelItemCollection)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }
 
        EditingContext Context
        { 
            get 
            {
                if (context == null) 
                {
                    IModelTreeItem modelTreeItem = this.Items as IModelTreeItem;
                    if (modelTreeItem != null)
                    { 
                        this.context = modelTreeItem.ModelTreeManager.Context;
                    } 
                } 
                return context;
            } 
        }

        public bool IsDefaultContainer
        { 
            get { return (bool)GetValue(IsDefaultContainerProperty); }
            set { SetValue(IsDefaultContainerProperty, value); } 
        } 

        [Fx.Tag.KnownXamlExternal] 
        public TypeResolvingOptions DroppingTypeResolvingOptions
        {
            get { return (TypeResolvingOptions)GetValue(DroppingTypeResolvingOptionsProperty); }
            set { SetValue(DroppingTypeResolvingOptionsProperty, value); } 
        }
 
        static void OnHintTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject; 
            itemsPresenter.UpdateHintTextVisibility(e.NewValue as string);
        }

        static void OnItemsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject; 
            itemsPresenter.OnItemsChanged(e.NewValue); 
        }
 
        static void OnItemsPanelChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            WorkflowItemsPresenter itemsPresenter = (WorkflowItemsPresenter)dependencyObject;
            itemsPresenter.panel.ItemsPanel = (ItemsPanelTemplate)e.NewValue; 
        }
 
        void OnItemsChanged(object newItems) 
        {
            ModelItemCollection newItemsCollection = (ModelItemCollection)newItems; 
            if (!isRegisteredWithParent)
            {
                CutCopyPasteHelper.RegisterWithParentViewElement(this);
                isRegisteredWithParent = true; 
            }
            populateOnLoad = false; 
            PopulateContent(); 
        }
 
        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // if this.Items is null, and we are getting a collection changed that
            // means this event some how happened before this can get the unloaded event 
            // and unsubscribe from this event.
            if (this.Items == null) 
            { 
                return;
            } 
            bool fullRepopulateNeeded = true;

            // when one item is dropped into this items presenter focus on the new view element for it.
            if (e.Action == NotifyCollectionChangedAction.Add 
                && e.NewItems != null
                && e.NewItems.Count == 1) 
            { 
                // insert itemview and spacer
                fullRepopulateNeeded = false; 
                int itemViewIndex = GetViewIndexForItem(e.NewStartingIndex);
                VirtualizedContainerService containerService = this.Context.Services.GetService();
                UIElement itemView = containerService.GetContainer((ModelItem)e.NewItems[0], this);
                this.panel.Items.Insert(itemViewIndex, itemView as UIElement); 
                // index 2 + i*2 + 1 is spacer i+1
                FrameworkElement spacer = CreateSpacer(); 
                this.panel.Items.Insert(itemViewIndex + 1, spacer); 

 
                ModelItem insertedItem = (ModelItem)e.NewItems[0];
                this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() =>
                {
                    UIElement view = (UIElement)insertedItem.View; 
                    if (view != null)
                    { 
                        Keyboard.Focus(view); 
                    }
                })); 
            }

            else if (e.Action == NotifyCollectionChangedAction.Remove)
            { 
                if (e.OldItems != null && e.OldItems.Count == 1)
                { 
                    fullRepopulateNeeded = false; 
                    int itemViewIndex = GetViewIndexForItem(e.OldStartingIndex);
                    this.panel.Items.RemoveAt(itemViewIndex); 
                    //remove spacer also
                    this.panel.Items.RemoveAt(itemViewIndex);
                }
 
                if (this.Items.Count == 0)
                { 
                    fullRepopulateNeeded = true; 
                }
 
                // deselect removed items
                if (this.Context != null)
                {
                    IList selectedItems = this.Context.Items.GetValue().SelectedObjects.ToList(); 
                    foreach (ModelItem selectedAndRemovedItem in selectedItems.Intersect(e.OldItems.Cast()))
                    { 
                        Selection.Toggle(this.Context, selectedAndRemovedItem); 
                    }
                } 
            }
            if (this.Items.Count > 0)
            {
                this.hintTextGrid.Visibility = Visibility.Collapsed; 
            }
            else 
            { 
                this.hintTextGrid.Visibility = Visibility.Visible;
            } 

            if (fullRepopulateNeeded)
            {
                PopulateContent(); 
            }
        } 
 
        protected override void OnInitialized(EventArgs e)
        { 
            base.OnInitialized(e);
            this.AllowDrop = true;
            this.Content = outerGrid;
            if (this.ItemsPanel != null) 
            {
                this.panel.ItemsPanel = this.ItemsPanel; 
            } 

            ICompositeViewEvents containerEvents = null; 
            bool isDefault = false;

            this.Loaded += (s, eventArgs) =>
            { 
                isDefault = this.IsDefaultContainer;
                selectedSpacerIndex = addAtEndMarker; 
                DependencyObject parent = VisualTreeHelper.GetParent(this); 
                while (null != parent && !typeof(ICompositeViewEvents).IsAssignableFrom(parent.GetType()))
                { 
                    parent = VisualTreeHelper.GetParent(parent);
                }
                containerEvents = parent as ICompositeViewEvents;
                if (null != containerEvents) 
                {
                    if (isDefault) 
                    { 
                        containerEvents.RegisterDefaultCompositeView(this);
                    } 
                    else
                    {
                        containerEvents.RegisterCompositeView(this);
                    } 
                }
                if (this.Items != null) 
                { 
                    //UnRegistering because of 137896: Inside tab control multiple Loaded events happen without an Unloaded event.
                    this.Items.CollectionChanged -= new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
                    this.Items.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
                }
                if (populateOnLoad)
                { 
                    this.PopulateContent();
                } 
            }; 

            this.Unloaded += (s, eventArgs) => 
            {
                if (null != containerEvents)
                {
                    if (isDefault) 
                    {
                        containerEvents.UnregisterDefaultCompositeView(this); 
                    } 
                    else
                    { 
                        containerEvents.UnregisterCompositeView(this);

                    }
                } 
                if (this.Items != null)
                { 
                    this.Items.CollectionChanged -= new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
                }
                populateOnLoad = true; 
            };
        }

        void PopulateContent() 
        {
            this.panel.Items.Clear(); 
 
            if (this.Items != null)
            { 

                // index 0 is header.
                ContentControl header = new ContentControl();
                header.Focusable = false; 
                header.ContentTemplate = this.HeaderTemplate;
                header.SetValue(IndexProperty, 0); 
                header.Drop += new DragEventHandler(OnSpacerDrop); 
                this.panel.Items.Add(header);
 
                // index 1 is first spacer
                FrameworkElement startSpacer = CreateSpacer();
                this.panel.Items.Add(startSpacer);
 
                foreach (ModelItem item in this.Items)
                { 
                    // index 2 + i*2 is itemView i 
                    VirtualizedContainerService containerService = this.Context.Services.GetService();
                    UIElement itemView = containerService.GetContainer(item, this); 
                    this.panel.Items.Add(itemView as UIElement);
                    // index 2 + i*2 + 1 is spacer i+1
                    FrameworkElement spacer = CreateSpacer();
                    this.panel.Items.Add(spacer); 
                }
                // index 2 + count*2 is footer 
                ContentControl footer = new ContentControl(); 
                footer.ContentTemplate = this.FooterTemplate;
                footer.Focusable = true; 
                footer.IsHitTestVisible = true;
                footer.IsTabStop = true;
                footer.SetValue(IndexProperty, addAtEndMarker);
                footer.Drop += new DragEventHandler(OnSpacerDrop); 
                footer.LostFocus += new RoutedEventHandler(OnSpacerLostFocus);
                footer.GotFocus += new RoutedEventHandler(OnSpacerGotFocus); 
                this.panel.Items.Add(footer); 
                footer.Focusable = false;
            } 
            UpdateHintTextVisibility(HintText);
        }

        int GetViewIndexForItem(int itemIndex) 
        {
            return 2 + itemIndex * 2; 
        } 

        int GetViewIndexForSpacer(int spacerIndex) 
        {
            return 2 + spacerIndex * 2 + 1;
        }
 
        int GetSpacerIndex(int viewIndex)
        { 
            if (viewIndex == 1) 
            {
                return 0; 
            }
            else
            {
                return (viewIndex - 3) / 2 + 1; 
            }
        } 
 
        void UpdateHintTextVisibility(string hintText)
        { 
            if (this.hintTextGrid != null && this.Items != null)
            {
                this.hintTextGrid.Visibility = (this.Items.Count == 0 && !string.IsNullOrEmpty(hintText)) ? Visibility.Visible : Visibility.Collapsed;
            } 
        }
 
        private FrameworkElement CreateSpacer() 
        {
            FrameworkElement spacer = (this.SpacerTemplate != null) ? (FrameworkElement)this.SpacerTemplate.LoadContent() : new Rectangle(); 
            spacer.IsHitTestVisible = true;
            Control spacerControl = spacer as Control;
            if (spacerControl != null)
            { 
                spacerControl.IsTabStop = true;
            } 
            spacer.Drop += new DragEventHandler(OnSpacerDrop); 
            spacer.LostFocus += new RoutedEventHandler(OnSpacerLostFocus);
            spacer.GotFocus += new RoutedEventHandler(OnSpacerGotFocus); 
            spacer.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(OnSpacerGotKeyboardFocus);
            spacer.MouseDown += new MouseButtonEventHandler(OnSpacerMouseDown);
            return spacer;
        } 

        void OnSpacerDrop(object sender, DragEventArgs e) 
        { 
            int index = GetSpacerIndexFromView(sender);
            OnItemDropped(e, index); 
        }

        private int GetSpacerIndexFromView(object sender)
        { 
            if (((DependencyObject)sender).ReadLocalValue(IndexProperty) != DependencyProperty.UnsetValue)
            { 
                int index = (int)((DependencyObject)sender).GetValue(IndexProperty); 
                return index;
            } 
            else
            {
                return GetSpacerIndex(this.panel.Items.IndexOf(sender));
            } 
        }
 
        void OnSpacerGotFocus(object sender, RoutedEventArgs e) 
        {
            int index = GetSpacerIndexFromView(sender); 
            selectedSpacerIndex = index;
        }

        void OnSpacerGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
        {
            // Handle the event so that it won't be routed to the containing designer to affect selection 
            if (handleSpacerGotKeyboardFocus) 
            {
                e.Handled = true; 
            }
        }

        void OnSpacerLostFocus(object sender, RoutedEventArgs e) 
        {
            int index = GetSpacerIndexFromView(sender); 
            selectedSpacerIndex = addAtEndMarker; 
        }
 
        void OnSpacerMouseDown(object sender, MouseButtonEventArgs e)
        {
            // Schedule the Keyboard.Focus command to let it execute later than WorkflowViewElement.OnMouseDown
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => 
            {
                this.handleSpacerGotKeyboardFocus = true; 
                Keyboard.Focus((FrameworkElement)sender); 
                this.handleSpacerGotKeyboardFocus = false;
            })); 
        }

        void OnItemDropped(DragEventArgs e, int index)
        { 
            DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.None);
            object droppedObject = DragDropHelper.GetDroppedObject(this, e, Context); 
            ICompositeView sourceContainer = DragDropHelper.GetCompositeView(e); 
            if (droppedObject != null)
            { 
                // move within this presenter case, dont set anything in e.Effects.
                // this just causes an change in ordering within the collection
                if (sourceContainer == this)
                { 
                    Fx.Assert(this.Items.Contains(droppedObject), "droppedObject should have been added to the Items collection");
                    int oldIndex; 
                    if (droppedObject is ModelItem) 
                    {
                        oldIndex = this.Items.IndexOf((ModelItem)droppedObject); 
                    }
                    else
                    {
                        oldIndex = ((IList)this.Items.GetCurrentValue()).IndexOf(droppedObject); 
                    }
                    // this check excludes the case where an item is dropped on to the spacer just before or just after itself. 
                    if (index != oldIndex && index != (oldIndex + 1)) 
                    {
                        //if element is placed ahead of old location, decrement the index not to include moved object 
                        if (oldIndex < index)
                        {
                            --index;
                        } 
                        this.Items.Remove(droppedObject);
                        InsertItem(index, droppedObject); 
                    } 
                }
                // dropped from elsewhere case, consider it a move. 
                else
                {
                    if (IsDropAllowed(droppedObject))
                    { 
                        InsertItem(index, droppedObject);
                        DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move); 
                    } 
                }
                e.Handled = true; 
            }

        }
 
        private bool IsDropAllowed(object droppedObject)
        { 
            bool isDropAllowed = false; 
            ModelItem modelItem = droppedObject as ModelItem;
            if (modelItem != null && !IsInParentChain(modelItem)) 
            {
                if (this.AllowedItemType.IsAssignableFrom(modelItem.ItemType))
                {
                    isDropAllowed = true; 
                }
            } 
            else if (droppedObject is Type && this.AllowedItemType.IsAssignableFrom((Type)droppedObject)) 
            {
                isDropAllowed = true; 
            }
            else
            {
                if (this.AllowedItemType.IsAssignableFrom(droppedObject.GetType())) 
                {
                    isDropAllowed = true; 
                } 
            }
            return isDropAllowed; 
        }

        private bool IsInParentChain(ModelItem droppedModelItem)
        { 
            bool isInParentChain = false;
            ModelItem parentModelItem = this.Items; 
            while (parentModelItem != null) 
            {
                if (parentModelItem == droppedModelItem) 
                {
                    isInParentChain = true;
                    break;
                } 
                parentModelItem = parentModelItem.Parent;
            } 
            return isInParentChain; 
        }
 
        void InsertItem(int index, object droppedObject)
        {
            ModelItem insertedItem = null;
            if (index == addAtEndMarker || index >= this.Items.Count) 
            {
                insertedItem = this.Items.Add(droppedObject); 
            } 
            else
            { 
                insertedItem = this.Items.Insert(index, droppedObject);
            }
            if (insertedItem != null)
            { 
                Selection.SelectOnly(this.Context, insertedItem);
            } 
        } 

        protected override void OnDrop(DragEventArgs e) 
        {
            int index = addAtEndMarker;
            WorkflowViewElement dropTarget = null;
            if (e.OriginalSource is WorkflowViewElement) 
            {
                dropTarget = (WorkflowViewElement)e.OriginalSource; 
            } 
            else
            { 
                dropTarget = VisualTreeUtils.FindFocusableParent((UIElement)e.OriginalSource);
            }

            if (null != dropTarget && null != dropTarget.ModelItem) 
            {
                int targetIndex = this.Items.IndexOf(dropTarget.ModelItem); 
                if (-1 != targetIndex) 
                {
                    index = targetIndex + 1; 
                }
            }
            OnItemDropped(e, index);
            base.OnDrop(e); 
        }
 
        void OnDrag(DragEventArgs e) 
        {
            if (!e.Handled) 
            {
                if (!DragDropHelper.AllowDrop(e.Data, this.Context, this.AllowedItemType))
                {
                    e.Effects = DragDropEffects.None; 
                }
                e.Handled = true; 
            } 
        }
 
        protected override void OnDragEnter(DragEventArgs e)
        {
            this.OnDrag(e);
            base.OnDragEnter(e); 
        }
 
        protected override void OnDragOver(DragEventArgs e) 
        {
            this.OnDrag(e); 
            base.OnDragOver(e);
        }

 
        public void OnItemMoved(ModelItem modelItem)
        { 
            if (this.Items.Contains(modelItem)) 
            {
                this.Items.Remove(modelItem); 
            }
        }

        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new WorkflowItemsPresenterAutomationPeer(this); 
        } 

        public object OnItemsCut(List itemsToCut) 
        {
            List orderMetaData = GetOrderMetaData(itemsToCut).ToList();
            foreach (ModelItem item in itemsToCut)
            { 
                this.Items.Remove(item);
                this.Context.Items.SetValue(new Selection(new ArrayList())); 
            } 
            return orderMetaData;
        } 

        public object OnItemsCopied(List itemsToCopy)
        {
            return GetOrderMetaData(itemsToCopy).ToList(); 
        }
 
        IList GetOrderMetaData(IList itemsToCopy) 
        {
            SortedList orderedList = new SortedList(); 
            foreach (ModelItem modelItem in itemsToCopy)
            {
                int index = this.Items.IndexOf(modelItem);
                if (index > -1) 
                {
                    orderedList.Add(index, modelItem.GetCurrentValue()); 
                } 
            }
            return orderedList.Values; 
        }

        public void OnItemsPasted(List itemsToPaste, List metaData, Point pastePoint, WorkflowViewElement pastePointReference)
        { 
            // first see if a spacer is selected.
            int index = this.selectedSpacerIndex; 
            // else see if we can paste after a selected child 
            if (index < 0)
            { 
                Selection currentSelection = this.Context.Items.GetValue();
                index = this.Items.IndexOf(currentSelection.PrimarySelection);
                //paste after the selected child
                if (index >= 0) 
                {
                    index++; 
                } 
            }
            if (index < 0) 
            {
                index = addAtEndMarker;
            }
 
            List mergedItemsToPaste = new List();
            if (metaData != null) 
            { 
                foreach (object metaDataObject in metaData)
                { 
                    List orderedItemsMetaData = metaDataObject as List;
                    if (orderedItemsMetaData != null)
                    {
                        foreach (object objectToPaste in orderedItemsMetaData) 
                        {
                            if (!mergedItemsToPaste.Contains(objectToPaste)) 
                            { 
                                mergedItemsToPaste.Add(objectToPaste);
                            } 
                        }
                    }
                }
            } 

            foreach (object itemToPaste in itemsToPaste) 
            { 
                if (!mergedItemsToPaste.Contains(itemToPaste))
                { 
                    mergedItemsToPaste.Add(itemToPaste);
                }
            }
 
            List modelItemsToSelect = new List();
 
            foreach (object itemToPaste in mergedItemsToPaste) 
            {
                if (IsDropAllowed(itemToPaste)) 
                {
                    if (index == addAtEndMarker)
                    {
                        modelItemsToSelect.Add(this.Items.Add(itemToPaste)); 
                    }
                    else 
                    { 
                        modelItemsToSelect.Add(this.Items.Insert(index, itemToPaste));
                    } 
                    if (index >= 0)
                    {
                        index++;
                    } 
                }
            } 
 
            this.Context.Items.SetValue(new Selection(modelItemsToSelect));
        } 

        public void OnItemsDelete(List itemsToDelete)
        {
            if (null != itemsToDelete) 
            {
                itemsToDelete.ForEach(p => 
                { 
                    if (null != this.Items && this.Items.Contains(p))
                    { 
                        this.Items.Remove(p);
                    }
                }
                    ); 
            }
        } 
 
        public bool CanPasteItems(List itemsToPaste)
        { 
            bool result = false;
            if (null != itemsToPaste && itemsToPaste.Count > 0)
            {
                result = itemsToPaste.All(p => this.IsDropAllowed(p)); 
            }
            return result; 
        } 

        class WorkflowItemsPresenterAutomationPeer : UIElementAutomationPeer 
        {
            WorkflowItemsPresenter owner;

            public WorkflowItemsPresenterAutomationPeer(WorkflowItemsPresenter owner) 
                : base(owner)
            { 
                this.owner = owner; 
            }
 
            protected override AutomationControlType GetAutomationControlTypeCore()
            {
                return AutomationControlType.Custom;
            } 

            protected override string GetAutomationIdCore() 
            { 
                string automationId = base.GetAutomationIdCore();
                if (string.IsNullOrEmpty(automationId)) 
                {
                    automationId = base.GetNameCore();
                    if (string.IsNullOrEmpty(automationId))
                    { 
                        automationId = this.owner.GetType().Name;
                    } 
                } 
                return automationId;
            } 

            protected override string GetNameCore()
            {
                // Return an empty string if some activites are dropped on the presenter 
                if (owner.Items.Count > 0)
                { 
                    return string.Empty; 
                }
                string name = base.GetNameCore(); 
                if (string.IsNullOrEmpty(name))
                {
                    name = this.owner.HintText;
                } 
                return name;
            } 
 
            protected override string GetClassNameCore()
            { 
                return this.owner.GetType().Name;
            }
        }
 
    }
} 

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