1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.View
7 using System.Collections.ObjectModel;
8 using System.Diagnostics.CodeAnalysis;
11 using System.Windows.Automation.Peers;
12 using System.Windows.Controls;
13 using System.Windows.Input;
14 using System.Windows.Media;
15 using Microsoft.Activities.Presentation;
17 // This class is used to resolve generic type in case when a generic activity is
18 // dropped on design surface
19 internal partial class ActivityTypeResolver : DialogWindow
21 public static readonly DependencyProperty GenericTypeMappingProperty =
22 DependencyProperty.Register("GenericTypeMapping",
23 typeof(ObservableCollection<TypeKeyValue>),
24 typeof(ActivityTypeResolver));
26 public static readonly DependencyProperty EditedTypeProperty =
27 DependencyProperty.Register("EditedType",
29 typeof(ActivityTypeResolver),
30 new PropertyMetadata(new PropertyChangedCallback(OnEditedTypeChanged)));
32 static readonly DependencyPropertyKey IsTypeResolvedKey =
33 DependencyProperty.RegisterReadOnly("IsTypeResolved",
35 typeof(ActivityTypeResolver),
36 new PropertyMetadata(false));
38 public static readonly DependencyProperty IsTypeResolvedProperty = IsTypeResolvedKey.DependencyProperty;
40 public ActivityTypeResolver()
42 InitializeComponent();
43 this.HelpKeyword = HelpKeywords.ActivityTypeResolver;
46 protected override void OnInitialized(EventArgs e)
48 base.OnInitialized(e);
49 SetValue(GenericTypeMappingProperty, new ObservableCollection<TypeKeyValue>());
50 this.Title = SR.TypeResolverWindowTitle;
51 this.typeResolver.Focus();
55 public Type ConcreteType
63 public Type EditedType
65 get { return (Type)GetValue(EditedTypeProperty); }
66 set { SetValue(EditedTypeProperty, value); }
69 public ObservableCollection<TypeKeyValue> GenericTypeMapping
71 get { return (ObservableCollection<TypeKeyValue>)GetValue(GenericTypeMappingProperty); }
72 set { SetValue(GenericTypeMappingProperty, value); }
75 public bool IsTypeResolved
77 get { return (bool)GetValue(IsTypeResolvedProperty); }
78 private set { SetValue(IsTypeResolvedKey, value); }
81 public TypeResolvingOptions Options
87 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes,
88 Justification = "Catching all exceptions to avoid VS Crash")]
89 [SuppressMessage("Reliability", "Reliability108", Justification = "Catching all exceptions to avoid VS Crash")]
90 public void NotifyTypeChanged(TypeKeyValue sender)
92 this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.ApplicationIdle,
97 IsTypeResolved = (null != ResolveType() ? true : false);
100 catch (Exception err)
102 SetError(err.Message);
103 IsTypeResolved = false;
108 private void SetError(string message)
110 if (this.GenericTypeMapping != null)
112 foreach (TypeKeyValue tkv in this.GenericTypeMapping)
115 tkv.ErrorText = message;
120 private void ClearError()
122 if (this.GenericTypeMapping != null)
124 foreach (TypeKeyValue tkv in this.GenericTypeMapping)
127 tkv.ErrorText = null;
133 protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
135 return new UIElementAutomationPeer(this);
138 static void OnEditedTypeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
140 ActivityTypeResolver resolver = (ActivityTypeResolver)sender;
141 resolver.OnEditTypeAssigned();
144 void OnCancelClick(object sender, RoutedEventArgs e)
146 DialogResult = false;
149 void OnEditTypeAssigned()
151 if (null != this.EditedType && this.EditedType.IsGenericTypeDefinition)
153 this.typeName.Text = TypeNameHelper.GetDisplayName(this.EditedType, false);
155 Type[] generics = this.EditedType.GetGenericArguments();
156 foreach (Type type in generics)
158 Type temp = type; // reference this temp variable instead of reference type in the anonymous delegate
159 TypeKeyValue tkv = new TypeKeyValue(type, new Action<TypeKeyValue>(NotifyTypeChanged))
162 Filter = delegate(Type t)
164 if (!TypeUtilities.CanSubstituteGenericParameter(temp, t))
169 return this.Options == null
170 || this.Options.Filter == null
171 || this.Options.Filter(t);
173 MostRecentlyUsedTypes = this.Options != null ? this.Options.MostRecentlyUsedTypes : null,
175 string hintText = null;
176 if (this.Options != null && this.Options.HintTextMap.TryGetValue(type.Name, out hintText))
178 tkv.HintText = hintText;
181 this.GenericTypeMapping.Add(tkv);
183 if (this.Options == null || !this.Options.BrowseTypeDirectly)
185 tkv.BrowseTypeDirectly = false;
186 //this has to happen after the tkv is added GenericTypeMapping because:
187 //when TargetType is set, TypeResolver will try to resolve the generic type with this TargetType as type argument,
188 //and when resolvig the type, TypeResolver needs to know all the mappings
189 if (tkv.MostRecentlyUsedTypes == null)
191 if (tkv.Filter == null || tkv.Filter(typeof(int)))
193 tkv.TargetType = typeof(int);
196 else if (tkv.MostRecentlyUsedTypes.Contains(typeof(int)))
198 tkv.TargetType = typeof(int);
200 else if (tkv.MostRecentlyUsedTypes.Count > 0)
202 tkv.TargetType = tkv.MostRecentlyUsedTypes[0];
209 void OnOkClick(object sender, RoutedEventArgs e)
213 Type type = ResolveType();
216 this.ConcreteType = type;
221 MessageBox.Show(SR.TypeResolverError, SR.TypeResolverErrorMessageTitle, MessageBoxButton.OK, MessageBoxImage.Error);
224 catch (ArgumentException err)
226 MessageBox.Show(err.Message, err.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
230 void TypeKeyDown(object sender, KeyEventArgs e)
232 if (TypePresenter.IsPreviewKey(e.Key))
234 ListViewItem typeView = (ListViewItem)sender;
235 //always focus on the type presenter so the presenter could handle keyboard events
236 TypePresenter typePresenter = FindChildElement<TypePresenter>(typeView);
237 if (typePresenter != null)
239 typePresenter.Preview();
245 ChildType FindChildElement<ChildType>(DependencyObject tree) where ChildType : DependencyObject
247 //recursively traverse the visual tree and find the element of a given type
248 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(tree); i++)
250 DependencyObject child = VisualTreeHelper.GetChild(tree, i);
251 if (child != null && child is ChildType)
253 return child as ChildType;
257 ChildType childInSubtree = FindChildElement<ChildType>(child);
258 if (childInSubtree != null)
260 return childInSubtree;
272 //get number of generic parameters in edited type
273 Type[] arguments = new Type[this.GenericTypeMapping.Count];
275 //for each argument, get resolved type
276 for (int i = 0; i < this.GenericTypeMapping.Count && isValid; ++i)
278 arguments[i] = this.GenericTypeMapping[i].GetConcreteType();
279 isValid = isValid && (null != arguments[i]);
281 //if all parameters are resolved, create concrete type
284 result = this.EditedType.MakeGenericType(arguments);