1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Core.Presentation
7 using System.Activities.Presentation;
8 using System.Activities.Presentation.Metadata;
9 using System.Activities.Presentation.Model;
10 using System.Activities.Presentation.View;
11 using System.Activities.Presentation.Services;
12 using System.Activities.Statements;
13 using System.Collections.ObjectModel;
14 using System.Collections.Specialized;
15 using System.ComponentModel;
16 using System.Diagnostics.CodeAnalysis;
20 using System.Windows.Input;
21 using System.Windows.Threading;
22 using System.Windows.Controls;
23 using System.Activities.Presentation.View.OutlineView;
26 /// Interaction logic for TryCatchDesigner.xaml
28 partial class TryCatchDesigner
30 const string CatchesPropertyName = "Catches";
31 const string ExceptionTypePropertyName = "ExceptionType";
32 const string ExpandViewStateKey = "IsExpanded";
34 public static readonly DependencyProperty ShowTryExpandedProperty =
35 DependencyProperty.Register(
38 typeof(TryCatchDesigner),
39 new UIPropertyMetadata(true)
42 public static readonly DependencyProperty ShowFinallyExpandedProperty =
43 DependencyProperty.Register(
44 "ShowFinallyExpanded",
46 typeof(TryCatchDesigner),
47 new UIPropertyMetadata(false)
50 public static readonly DependencyProperty ShowTypePresenterExpandedProperty =
51 DependencyProperty.Register(
52 "ShowTypePresenterExpanded",
54 typeof(TryCatchDesigner),
55 new UIPropertyMetadata(false)
58 public static readonly DependencyProperty SelectedCatchProperty =
59 DependencyProperty.Register(
62 typeof(TryCatchDesigner),
63 new UIPropertyMetadata(null));
65 static ObservableCollection<Type> mostRecentlyUsedTypes;
66 static ObservableCollection<Type> MostRecentlyUsedTypes
70 if (mostRecentlyUsedTypes == null)
72 mostRecentlyUsedTypes = new ObservableCollection<Type>
74 typeof(ArgumentException),
75 typeof(NullReferenceException),
77 typeof(InvalidOperationException),
81 return mostRecentlyUsedTypes;
85 public bool ShowTryExpanded
89 return (bool)this.GetValue(ShowTryExpandedProperty);
93 this.SetValue(ShowTryExpandedProperty, value);
97 public bool ShowFinallyExpanded
101 return (bool)this.GetValue(ShowFinallyExpandedProperty);
105 this.SetValue(ShowFinallyExpandedProperty, value);
109 public bool ShowTypePresenterExpanded
113 return (bool)this.GetValue(ShowTypePresenterExpandedProperty);
117 this.SetValue(ShowTypePresenterExpandedProperty, value);
121 ModelItem SelectedCatch
125 return (ModelItem)this.GetValue(SelectedCatchProperty);
129 this.SetValue(SelectedCatchProperty, value);
133 TypePresenter typePresenter;
134 Label addCatchHintLabel;
136 internal static void RegisterMetadata(AttributeTableBuilder builder)
138 Type type = typeof(TryCatch);
139 builder.AddCustomAttributes(type, new DesignerAttribute(typeof(TryCatchDesigner)));
140 builder.AddCustomAttributes(type, type.GetProperty("Try"), BrowsableAttribute.No);
141 builder.AddCustomAttributes(type, type.GetProperty("Finally"), BrowsableAttribute.No);
142 builder.AddCustomAttributes(type, type.GetProperty("Catches"), BrowsableAttribute.No);
143 builder.AddCustomAttributes(type, type.GetProperty("Variables"), BrowsableAttribute.No);
145 // Make Catches collection's node visible in the document treeview but hide Catches node itself.
146 builder.AddCustomAttributes(type, type.GetProperty("Catches"), new ShowPropertyInOutlineViewAttribute() { CurrentPropertyVisible = false });
149 [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
150 public TryCatchDesigner()
152 InitializeComponent();
154 this.Loaded += OnLoaded;
155 this.Unloaded += OnUnloaded;
158 void OnLoaded(object sender, RoutedEventArgs e)
160 this.Context.Items.Subscribe<Selection>(OnSelectionChanged);
161 // at this time, this.ModelItem is already set
162 this.ModelItem.PropertyChanged += OnModelItemPropertyChanged;
163 this.ModelItem.Properties[CatchesPropertyName].Collection.CollectionChanged += OnModelItemCollectionChanged;
165 ViewStateService viewStateService = this.Context.Services.GetService<ViewStateService>();
167 foreach (ModelItem modelItem in this.ModelItem.Properties["Catches"].Collection)
169 bool? isExpanded = (bool?)viewStateService.RetrieveViewState(modelItem, ExpandViewStateKey);
170 if (isExpanded != null && isExpanded.Value)
172 this.SelectedCatch = modelItem;
174 CollapseFinallyView();
180 void OnUnloaded(object sender, RoutedEventArgs e)
182 this.ModelItem.PropertyChanged -= OnModelItemPropertyChanged;
183 this.ModelItem.Properties[CatchesPropertyName].Collection.CollectionChanged -= OnModelItemCollectionChanged;
184 this.Context.Items.Unsubscribe<Selection>(OnSelectionChanged);
187 void OnModelItemPropertyChanged(object sender, PropertyChangedEventArgs e)
189 switch (e.PropertyName)
204 void OnModelItemCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
206 // to update the filter
207 this.typePresenter.Filter = this.ExceptionTypeFilter;
210 void OnSelectionChanged(Selection selection)
212 if (IsDescendantOfTry(selection.PrimarySelection))
214 this.ExpandTryView();
216 else if (IsDescendantOfFinally(selection.PrimarySelection))
218 this.ExpandFinallyView();
222 foreach (ModelItem catchObject in this.ModelItem.Properties["Catches"].Collection)
224 if (IsDescendantOfCatch(catchObject, selection.PrimarySelection))
226 UpdateSelection(catchObject);
233 bool IsDescendantOfTry(ModelItem descendant)
235 return IsDescendantOf(descendant, "Try");
238 bool IsDescendantOfFinally(ModelItem descendant)
240 return IsDescendantOf(descendant, "Finally");
243 static bool IsAncestorOf(ModelItem ancester, ModelItem descendant)
245 if (ancester == null)
250 ModelItem itr = descendant;
262 bool IsDescendantOf(ModelItem descendant, string property)
264 if (descendant == null)
270 ModelItem propertyValue = this.ModelItem.Properties[property].Value;
271 return IsAncestorOf(propertyValue, descendant);
275 internal static bool IsDescendantOfCatch(ModelItem catchObject, ModelItem descendant)
277 Fx.Assert(catchObject != null, "Catch object mustn't be null.");
278 if (catchObject == descendant)
284 ModelItem activityAction = catchObject.Properties["Action"].Value;
285 if (activityAction != null)
287 ModelItem activityActionHandler = activityAction.Properties["Handler"].Value;
288 if (activityActionHandler != null)
290 return IsAncestorOf(activityActionHandler, descendant);
297 void UpdateSelection(ModelItem newSelectedCatch)
299 ModelItem oldSelectedCatch = this.SelectedCatch;
300 this.SelectedCatch = newSelectedCatch;
302 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
304 if (oldSelectedCatch != null)
306 CatchDesigner oldSelectedCatchDesigner = (CatchDesigner)oldSelectedCatch.View;
307 if (oldSelectedCatchDesigner != null)
309 oldSelectedCatchDesigner.ExpandState = false;
310 oldSelectedCatchDesigner.PinState = false;
313 if (newSelectedCatch != null)
316 CollapseFinallyView();
317 CatchDesigner newSelectedCatchDesigner = (CatchDesigner)newSelectedCatch.View;
318 if (newSelectedCatchDesigner != null)
320 newSelectedCatchDesigner.ExpandState = true;
321 newSelectedCatchDesigner.PinState = true;
327 void CreateCatch(Type exceptionType)
329 if (exceptionType != null)
331 Type catchType = typeof(Catch<>).MakeGenericType(exceptionType);
332 object catchObject = Activator.CreateInstance(catchType);
334 Type activityActionType = typeof(ActivityAction<>).MakeGenericType(exceptionType);
335 object activityAction = Activator.CreateInstance(activityActionType);
337 Type argumentType = typeof(DelegateInArgument<>).MakeGenericType(exceptionType);
338 object exceptionArgument = Activator.CreateInstance(argumentType);
339 DelegateInArgument delegateArgument = exceptionArgument as DelegateInArgument;
340 Fx.Assert(null != delegateArgument, "delegate argument must be of DelegateInArgument type!");
341 delegateArgument.Name = "exception";
343 catchType.GetProperty(PropertyNames.Action).SetValue(catchObject, activityAction, null);
344 activityActionType.GetProperty(PropertyNames.ActionArgument).SetValue(activityAction, exceptionArgument, null);
346 this.ModelItem.Properties["Catches"].Collection.Add(catchObject);
350 void OnFinallyViewMouseDown(object sender, MouseButtonEventArgs e)
352 if (e.LeftButton == MouseButtonState.Pressed && e.ClickCount == 2)
354 SwitchTryCatchDesignerHelper.MakeRootDesigner(this);
357 else if (e.LeftButton == MouseButtonState.Pressed)
360 Keyboard.Focus((IInputElement)sender);
362 else if (e.RightButton == MouseButtonState.Pressed)
364 if (this.IsExpanded(this.ShowFinallyExpanded))
366 Keyboard.Focus((IInputElement)sender);
372 void OnFinallyViewMouseUp(object sender, MouseButtonEventArgs e)
374 // avoid context menu upon right-click when it's collapsed
375 if (!IsExpanded(this.ShowFinallyExpanded) && e.RightButton == MouseButtonState.Released)
381 bool IsExpanded(bool isExpanded)
383 DesignerView designerView = this.Context.Services.GetService<DesignerView>();
384 return isExpanded || designerView.ShouldExpandAll;
387 void OnTryViewMouseDown(object sender, MouseButtonEventArgs e)
389 if (e.LeftButton == MouseButtonState.Pressed && e.ClickCount == 2)
391 SwitchTryCatchDesignerHelper.MakeRootDesigner(this);
394 else if (e.LeftButton == MouseButtonState.Pressed)
397 Keyboard.Focus((IInputElement)sender);
399 else if (e.RightButton == MouseButtonState.Pressed)
401 if (this.IsExpanded(this.ShowTryExpanded))
403 Keyboard.Focus((IInputElement)sender);
409 void OnTryViewMouseUp(object sender, MouseButtonEventArgs e)
411 // avoid context menu upon right-click when it's collapsed
412 if (!IsExpanded(this.ShowTryExpanded) && e.RightButton == MouseButtonState.Released)
418 void ExpandFinallyView()
420 UpdateSelection(null);
421 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
423 this.ShowTryExpanded = false;
424 this.ShowFinallyExpanded = true;
430 UpdateSelection(null);
431 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
433 this.ShowFinallyExpanded = false;
434 this.ShowTryExpanded = true;
438 void CollapseFinallyView()
440 this.ShowFinallyExpanded = false;
443 void CollapseTryView()
445 this.ShowTryExpanded = false;
448 void OnTryViewKeyDown(object sender, KeyEventArgs e)
450 if (sender == e.OriginalSource && (e.Key == Key.Space || e.Key == Key.Enter))
457 void OnFinallyViewKeyDown(object sender, KeyEventArgs e)
459 if (sender == e.OriginalSource && (e.Key == Key.Space || e.Key == Key.Enter))
466 #region AddCatch Label & TypePresenter
468 void OnAddCatchMouseDown(object sender, MouseButtonEventArgs e)
470 if (e.LeftButton == MouseButtonState.Pressed)
472 this.SwitchToChooseException();
477 void OnAddCatchGotFocus(object sender, RoutedEventArgs e)
479 this.SwitchToChooseException();
483 void SwitchToChooseException()
485 this.ShowTypePresenterExpanded = true;
486 this.typePresenter.FocusOnVisibleControl();
489 void SwitchToHintText()
491 this.typePresenter.Type = null;
492 this.ShowTypePresenterExpanded = false;
493 Keyboard.Focus((IInputElement)this);
496 void OnAddCatchHintLabelLoaded(object sender, RoutedEventArgs e)
498 this.addCatchHintLabel = (Label)sender;
501 void OnAddCatchHintLabelUnloaded(object sender, RoutedEventArgs e)
503 this.addCatchHintLabel = null;
506 void OnTypePresenterLoaded(object sender, RoutedEventArgs e)
508 TypePresenter tp = (TypePresenter)sender;
509 Fx.Assert(tp != null, "sender must be a TypePresenter.");
511 this.typePresenter = tp;
512 this.typePresenter.Filter = this.ExceptionTypeFilter;
513 this.typePresenter.MostRecentlyUsedTypes = MostRecentlyUsedTypes;
514 //UnRegistering because of 137896: Inside tab control multiple Loaded events happen without an Unloaded event.
515 this.typePresenter.TypeBrowserClosed -= OnTypePresenterTypeBrowserClosed;
516 this.typePresenter.TypeBrowserClosed += OnTypePresenterTypeBrowserClosed;
519 void OnTypePresenterUnloaded(object sender, RoutedEventArgs e)
521 if (this.typePresenter != null)
523 this.typePresenter.TypeBrowserClosed -= OnTypePresenterTypeBrowserClosed;
524 this.typePresenter = null;
528 void OnTypePresenterTypeBrowserClosed(object sender, RoutedEventArgs e)
530 this.typePresenter.FocusOnVisibleControl();
533 void OnTypePresenterKeyDown(object sender, KeyEventArgs e)
538 this.SwitchToHintText();
549 void OnTypePresenterLostFocus(object sender, RoutedEventArgs e)
551 if (this.ShowTypePresenterExpanded)
560 if (this.typePresenter != null)
562 Type type = this.typePresenter.Type;
563 if (type != null && this.ExceptionTypeFilter(type))
567 this.SwitchToHintText();
573 bool ExceptionTypeFilter(Type type)
580 if (type != typeof(Exception) && !type.IsSubclassOf(typeof(Exception)))
585 ModelProperty catchesProperty = this.ModelItem.Properties[CatchesPropertyName];
586 Fx.Assert(catchesProperty != null, "TryCatch.Catches could not be null");
587 ModelItemCollection catches = catchesProperty.Collection;
588 Fx.Assert(catches != null, "Catches.Collection could not be null");
589 foreach (ModelItem catchItem in catches)
591 ModelProperty exceptionTypeProperty = catchItem.Properties[ExceptionTypePropertyName];
592 Fx.Assert(exceptionTypeProperty != null, "Catch.ExceptionType could not be null");
593 Type exceptionType = exceptionTypeProperty.ComputedValue as Type;
594 Fx.Assert(exceptionType != null, "Catch.ExceptionType.Value could not be null");
596 if (exceptionType == type)