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