1 //---------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //---------------------------------------------------------------- 4 5 namespace System.Activities.Presentation 6 { 7 using System; 8 using System.Activities.Presentation.Model; 9 using System.Activities.Presentation.View; 10 using System.Collections; 11 using System.Collections.Generic; 12 using System.Collections.ObjectModel; 13 using System.Collections.Specialized; 14 using System.Diagnostics.CodeAnalysis; 15 using System.Globalization; 16 using System.Linq; 17 using System.Runtime; 18 using System.Windows; 19 using System.Windows.Controls; 20 using System.Windows.Input; 21 using System.ComponentModel; 22 using System.Windows.Threading; 23 using System.Windows.Data; 24 using Microsoft.Activities.Presentation; 25 26 [Fx.Tag.XamlVisible(false)] 27 partial class TypeCollectionDesigner 28 { 29 public static readonly DependencyProperty ContextProperty = DependencyProperty.Register( 30 "Context", 31 typeof(EditingContext), 32 typeof(TypeCollectionDesigner), 33 new UIPropertyMetadata(null)); 34 35 [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", 36 Justification = "Type RoutedCommand is immutable.")] 37 public static readonly ICommand AddNewTypeCommand = new RoutedCommand("AddNewType", typeof(TypeCollectionDesigner)); 38 public static readonly ICommand DeleteTypeCommand = new RoutedCommand("DeleteType", typeof(TypeCollectionDesigner)); 39 40 DataGridHelper dgHelper; 41 ObservableCollection<TypeWrapper> wrapperCollection; 42 TypeCollectionDesigner()43 public TypeCollectionDesigner() 44 { 45 this.DefaultType = typeof(Object); 46 InitializeComponent(); 47 } 48 49 // The collection of Type objects to display when type collection designer is opened. 50 internal IEnumerable<Type> InitialTypeCollection 51 { 52 set 53 { 54 this.wrapperCollection = new ObservableCollection<TypeWrapper>(value.Select(type => new TypeWrapper(type))); 55 this.typesDataGrid.ItemsSource = this.wrapperCollection; 56 } 57 } 58 59 // The collction of Type objects in the type collection designer when user clicks OK. 60 public IEnumerable<Type> UpdatedTypeCollection 61 { 62 get 63 { 64 return wrapperCollection.Where(wrapper => wrapper.Type != null).Select(wrapper => wrapper.Type); 65 } 66 } 67 68 public EditingContext Context 69 { 70 get { return (EditingContext)GetValue(ContextProperty); } 71 set { SetValue(ContextProperty, value); } 72 } 73 74 public bool AllowDuplicate 75 { 76 get; 77 set; 78 } 79 80 public Func<Type, bool> Filter 81 { 82 get; 83 set; 84 } 85 86 public Type DefaultType 87 { 88 get; 89 set; 90 } 91 92 internal WorkflowElementDialog ParentDialog 93 { 94 get; 95 set; 96 } 97 OnOK()98 internal bool OnOK() 99 { 100 if (!this.AllowDuplicate) 101 { 102 List<TypeWrapper> list = new List<TypeWrapper>(); 103 foreach (TypeWrapper tw in this.wrapperCollection) 104 { 105 if (tw.Type != null && list.Any<TypeWrapper>(entry => Type.Equals(entry.Type, tw.Type))) 106 { 107 ErrorReporting.ShowErrorMessage(string.Format(CultureInfo.CurrentCulture, (string)this.FindResource("duplicateEntryErrorMessage"), TypeNameHelper.GetDisplayName(tw.Type, true))); 108 return false; 109 } 110 list.Add(tw); 111 } 112 } 113 return true; 114 } 115 116 // The DataGrid does not bubble up KeyDown event and we expect the upper window to be closed when ESC key is down. 117 // Thus we added an event handler in DataGrid to handle ESC key and closes the uppper window. OnTypesDataGridRowKeyDown(object sender, KeyEventArgs args)118 void OnTypesDataGridRowKeyDown(object sender, KeyEventArgs args) 119 { 120 DataGridRow row = (DataGridRow)sender; 121 if (args.Key == Key.Escape && !row.IsEditing && this.ParentDialog != null) 122 { 123 this.ParentDialog.CloseDialog(false); 124 } 125 } 126 OnInitialized(EventArgs e)127 protected override void OnInitialized(EventArgs e) 128 { 129 this.dgHelper = new DataGridHelper(this.typesDataGrid, this); 130 this.dgHelper.AddNewRowContent = this.FindResource("addNewRowLabel"); 131 this.dgHelper.AddNewRowCommand = AddNewTypeCommand; 132 133 base.OnInitialized(e); 134 } 135 OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)136 void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) 137 { 138 this.ButtonDelete.IsEnabled = 139 (this.typesDataGrid.SelectedItems != null) 140 && (this.typesDataGrid.SelectedItems.Count != 0); 141 } 142 OnAddTypeExecuted(object sender, ExecutedRoutedEventArgs e)143 void OnAddTypeExecuted(object sender, ExecutedRoutedEventArgs e) 144 { 145 var newEntry = new TypeWrapper(this.DefaultType); 146 this.wrapperCollection.Add(newEntry); 147 this.dgHelper.BeginRowEdit(newEntry); 148 e.Handled = true; 149 } 150 OnDeleteTypeExecuted(object sender, ExecutedRoutedEventArgs e)151 void OnDeleteTypeExecuted(object sender, ExecutedRoutedEventArgs e) 152 { 153 DataGridHelper.OnDeleteSelectedItems(this.typesDataGrid); 154 } 155 OnEditingControlLoaded(object sender, RoutedEventArgs args)156 void OnEditingControlLoaded(object sender, RoutedEventArgs args) 157 { 158 DataGridHelper.OnEditingControlLoaded(sender, args); 159 } 160 OnEditingControlUnloaded(object sender, RoutedEventArgs args)161 void OnEditingControlUnloaded(object sender, RoutedEventArgs args) 162 { 163 DataGridHelper.OnEditingControlUnloaded(sender, args); 164 } 165 166 sealed class TypeWrapper : DependencyObject 167 { 168 public static readonly DependencyProperty TypeProperty = 169 DependencyProperty.Register("Type", typeof(Type), typeof(TypeWrapper)); 170 171 //Default constructor is required by DataGrid to load NewItemPlaceHolder row and this constructor will never be called. 172 //Since we've already customized the new row template and hooked over creating new object event. TypeWrapper()173 public TypeWrapper() 174 { 175 throw FxTrace.Exception.AsError(new NotSupportedException()); 176 } 177 TypeWrapper(Type type)178 public TypeWrapper(Type type) 179 { 180 this.Type = type; 181 } 182 183 public Type Type 184 { 185 get { return (Type)GetValue(TypeProperty); } 186 set { SetValue(TypeProperty, value); } 187 } 188 189 // For screen reader to read the DataGrid row. ToString()190 public override string ToString() 191 { 192 if (this.Type != null && !string.IsNullOrEmpty(this.Type.Name)) 193 { 194 return this.Type.Name; 195 } 196 return "null"; 197 } 198 } 199 } 200 } 201