1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Presentation.View
7 using System.Activities.Presentation;
8 using System.Activities.Presentation.Internal.PropertyEditing;
9 using System.Activities.Presentation.Model;
10 using System.Activities.Presentation.Services;
11 using System.Activities.XamlIntegration;
12 using System.ComponentModel;
13 using System.Diagnostics.CodeAnalysis;
14 using System.Globalization;
16 using System.ServiceModel.Activities;
18 using System.Windows.Controls;
19 using System.Windows.Media;
20 using System.Collections.Generic;
22 [Fx.Tag.XamlVisible(false)]
23 public class WorkflowViewService : ViewService
25 EditingContext context;
27 public WorkflowViewService(EditingContext context)
29 Fx.Assert(context != null, "The passed in EditingContext is null");
30 this.context = context;
32 public event EventHandler<ViewCreatedEventArgs> ViewCreated;
34 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
35 Justification = "Catch all exceptions to prevent crash and always return the error view of the designer with the error message")]
36 [SuppressMessage("Reliability", "Reliability108:IsFatalRule",
37 Justification = "Catch all exceptions to prevent crash and always return the error view of the designer with the error message")]
38 public WorkflowViewElement GetViewElement(ModelItem modelItem)
40 WorkflowViewElement viewElement = null;
41 string errorString = string.Empty;
42 if (modelItem == null)
49 // try to make one from the type specified in Designer attribute.
50 // reuse existing views that are not currently parented
51 if (modelItem.View != null && ((WorkflowViewElement)modelItem.View).Parent == null)
53 viewElement = (WorkflowViewElement)modelItem.View;
57 viewElement = CreateViewElement(modelItem);
60 // now we successfully got a viewElement, lets initialize it with ModelItem;
61 if (viewElement != null)
63 viewElement.Context = this.context;
64 viewElement.ModelItem = modelItem;
65 ((IModelTreeItem)modelItem).SetCurrentView(viewElement);
66 viewElement.DataContext = viewElement;
68 // Generate an event that we created a new view element. This could be used by
69 // the Debugger Service to insert a breakpoint on the view element.
70 if (this.ViewCreated != null)
72 this.ViewCreated(this, new ViewCreatedEventArgs(viewElement));
77 // always report error to the customer.
80 errorString = e.ToString();
82 if (viewElement == null || !(string.IsNullOrEmpty(errorString)))
84 viewElement = GenerateErrorElement(modelItem, errorString);
89 internal static void ShowErrorInViewElement(WorkflowViewElement errorElement, string windowText, string toolTipText)
91 Grid errorGrid = new Grid();
92 errorGrid.Background = Brushes.Red;
93 errorGrid.Margin = new Thickness(20.0);
94 TextBlock text = new TextBlock();
95 text.Text = windowText;
96 text.Foreground = SystemColors.WindowBrush;
97 errorGrid.Children.Add(text);
98 errorGrid.ToolTip = toolTipText;
99 errorElement.Content = errorGrid;
102 private WorkflowViewElement GenerateErrorElement(ModelItem modelItem, string errorString)
104 WorkflowViewElement errorElement = new WorkflowViewElement();
105 string errorText = string.Format(CultureInfo.CurrentCulture, SR.CouldNotGenerateView, modelItem.ItemType.Name);
106 ShowErrorInViewElement(errorElement, errorText, errorString);
107 errorElement.Context = this.context;
108 errorElement.ModelItem = modelItem;
109 ((IModelTreeItem)modelItem).SetCurrentView(errorElement);
110 errorElement.DataContext = errorElement;
114 DesignerAttribute GetDesignerAttribute(Type type)
116 DesignerAttribute designerAttribute = null;
117 //do not return designers for IValueSerializableExpression (i.e. VisualBasicValue or VisualBasicReference
118 if (!typeof(IValueSerializableExpression).IsAssignableFrom(type))
120 designerAttribute = GetAttribute<DesignerAttribute>(type);
122 return designerAttribute;
125 internal static T GetAttribute<T>(Type type) where T : Attribute
127 T attribute = ExtensibilityAccessor.GetAttribute<T>(type);
128 if (attribute == null && type.IsGenericType)
130 attribute = ExtensibilityAccessor.GetAttribute<T>(type.GetGenericTypeDefinition());
135 //Returns the designer type based on the DesignerAttribute associated with the passed in type.
136 internal Type GetDesignerType(Type type)
138 return GetDesignerType(type, false);
141 internal Type GetDesignerType(Type type, bool throwOnFailure)
143 Type designerType = null;
144 // Try to identify a designer using the DesignerAttribute, either on the type or from MetaDataStore
145 DesignerAttribute designerAttribute = GetDesignerAttribute(type);
146 if (designerAttribute != null && !String.IsNullOrEmpty(designerAttribute.DesignerTypeName))
148 designerType = Type.GetType(designerAttribute.DesignerTypeName, throwOnFailure);
150 //if we have generic activity, check if there is a designer defined at type definition i.e. Assign<T>,
151 //rather then using a default one (which happens to be ActivityDesigner)
152 if (type.IsGenericType && Type.Equals(designerType, typeof(ActivityDesigner)))
154 Type genericType = type.GetGenericTypeDefinition();
155 DesignerAttribute genericDesignerAttribute =
156 TypeDescriptor.GetAttributes(genericType)[typeof(DesignerAttribute)] as DesignerAttribute;
158 (null == genericDesignerAttribute ?
159 designerType : Type.GetType(genericDesignerAttribute.DesignerTypeName, throwOnFailure));
165 protected WorkflowViewElement CreateViewElement(ModelItem modelItem)
167 Fx.Assert(modelItem != null, "The passed in ModelItem is null");
168 WorkflowViewElement viewElement = null;
170 Type designerType = GetDesignerType(modelItem.ItemType, true);
172 if (designerType != null && typeof(WorkflowViewElement).IsAssignableFrom(designerType))
174 viewElement = (WorkflowViewElement)Activator.CreateInstance(designerType);
179 internal WorkflowViewElement CreateDetachedViewElement(ModelItem modelItem)
181 WorkflowViewElement viewElement = CreateViewElement(modelItem);
183 // now we successfully got a viewElement, lets initialize it with ModelItem;
184 if (viewElement != null)
186 viewElement.Context = this.context;
187 viewElement.ModelItem = modelItem;
188 viewElement.DataContext = viewElement;
194 public override ModelItem GetModel(DependencyObject view)
198 throw FxTrace.Exception.AsError(new ArgumentNullException("view"));
201 if (view is WorkflowViewElement)
203 return ((WorkflowViewElement)view).ModelItem;
206 Fx.Assert("we should know if somebody is trying to get model item from thing other than WorkflowViewElement");
210 public override DependencyObject GetView(ModelItem model)
212 return GetViewElement(model);
215 internal bool ShouldAppearOnBreadCrumb(ModelItem modelItem, bool checkIfCanBeMadeRoot)
217 bool shouldAppearOnBreadCrumb = false;
218 if (modelItem != null)
220 Type designerType = this.GetDesignerType(modelItem.ItemType);
221 if (null != designerType)
223 if (checkIfCanBeMadeRoot)
225 ActivityDesignerOptionsAttribute options = WorkflowViewService.GetAttribute<ActivityDesignerOptionsAttribute>(modelItem.ItemType);
226 shouldAppearOnBreadCrumb = (typeof(WorkflowViewElement).IsAssignableFrom(designerType) &&
227 (typeof(ActivityDesigner) != designerType || ActivityDelegateUtilities.HasActivityDelegate(modelItem.ItemType)) &&
228 typeof(WorkflowService) != designerType &&
229 (options == null || options.AllowDrillIn));
233 shouldAppearOnBreadCrumb = typeof(WorkflowViewElement).IsAssignableFrom(designerType);
237 return shouldAppearOnBreadCrumb;