Code:
/ 4.0 / 4.0 / untmp / 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
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DecimalAnimation.cs
- TlsnegoTokenAuthenticator.cs
- SdlChannelSink.cs
- BaseInfoTable.cs
- ServiceObjectContainer.cs
- Stackframe.cs
- GridViewCommandEventArgs.cs
- RequestCache.cs
- NegotiateStream.cs
- DynamicUpdateCommand.cs
- Viewport3DVisual.cs
- TemplateControlParser.cs
- KeyValueConfigurationElement.cs
- SafeRegistryKey.cs
- TypeConvertions.cs
- ObjectStateManager.cs
- XmlSchemaCollection.cs
- EpmHelper.cs
- ActiveXHost.cs
- TemplateBaseAction.cs
- DataGridLength.cs
- TaskSchedulerException.cs
- RadioButton.cs
- NavigationFailedEventArgs.cs
- DirectoryRedirect.cs
- ListSourceHelper.cs
- SaveLedgerEntryRequest.cs
- DelegatingHeader.cs
- ValueExpressions.cs
- EncoderFallback.cs
- EmbeddedMailObject.cs
- ViewCellRelation.cs
- SqlXmlStorage.cs
- RegexMatchCollection.cs
- SecureConversationServiceCredential.cs
- SQLRoleProvider.cs
- SqlProviderManifest.cs
- EventsTab.cs
- DiscoveryMessageSequenceCD1.cs
- Timer.cs
- RoleManagerEventArgs.cs
- EventLogLink.cs
- SqlStream.cs
- FillRuleValidation.cs
- thaishape.cs
- _DisconnectOverlappedAsyncResult.cs
- XmlSchemaAnnotation.cs
- EncryptedData.cs
- AccessDataSourceWizardForm.cs
- GeneralTransform.cs
- LocatorPartList.cs
- AdCreatedEventArgs.cs
- returneventsaver.cs
- SafeSecurityHandles.cs
- CachingHintValidation.cs
- SchemaTableColumn.cs
- BindingCompleteEventArgs.cs
- FrameSecurityDescriptor.cs
- OdbcEnvironment.cs
- SapiInterop.cs
- MessageBox.cs
- MissingMemberException.cs
- Border.cs
- GeneralTransform2DTo3DTo2D.cs
- ConfigurationValue.cs
- Gdiplus.cs
- Material.cs
- RequestQueryProcessor.cs
- UIInitializationException.cs
- StandardCommands.cs
- WebPartPersonalization.cs
- GridViewHeaderRowPresenter.cs
- Bitmap.cs
- Tracking.cs
- FontStretchConverter.cs
- SystemThemeKey.cs
- QuaternionIndependentAnimationStorage.cs
- InstanceOwnerQueryResult.cs
- StylusPlugin.cs
- WebPartMenu.cs
- AbstractDataSvcMapFileLoader.cs
- ParameterBuilder.cs
- DataGridViewRowHeaderCell.cs
- NonValidatingSecurityTokenAuthenticator.cs
- WorkflowServiceNamespace.cs
- WaveHeader.cs
- XmlSchemaAnnotation.cs
- ListViewPagedDataSource.cs
- ColumnMapCopier.cs
- LayoutTableCell.cs
- ImmutableObjectAttribute.cs
- EventEntry.cs
- DataGridViewRowCancelEventArgs.cs
- PerformanceCountersElement.cs
- NetSectionGroup.cs
- DelimitedListTraceListener.cs
- CriticalExceptions.cs
- PropertyPathWorker.cs
- DataGridCell.cs
- OrderPreservingPipeliningMergeHelper.cs