1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System
.Workflow
.Activities
.Design
8 using System
.Collections
.Generic
;
9 using System
.ComponentModel
;
11 using System
.Reflection
;
13 using System
.ServiceModel
;
14 using System
.Windows
.Forms
;
15 using System
.Windows
.Forms
.Design
;
16 using System
.Workflow
.Activities
;
17 using System
.Workflow
.ComponentModel
;
18 using System
.Workflow
.ComponentModel
.Design
;
20 partial class OperationPickerDialog
: Form
22 private OperationInfoBase selectedOperation
;
23 private ServiceContractListItemList serviceContracts
;
24 private IServiceProvider serviceProvider
= null;
26 public OperationPickerDialog(IServiceProvider serviceProvider
, bool allowNewContracts
)
28 if (serviceProvider
== null)
30 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("serviceProvider");
32 this.serviceProvider
= serviceProvider
;
34 IUIService uisvc
= (IUIService
) this.serviceProvider
.GetService(typeof(IUIService
));
37 this.Font
= (Font
) uisvc
.Styles
["DialogFont"];
39 InitializeComponent();
40 this.serviceContracts
= new ServiceContractListItemList(this.operationsListBox
);
41 this.operationsListBox
.ServiceProvider
= this.serviceProvider
;
42 this.toolStripButton1
.Visible
= allowNewContracts
;
45 public OperationInfoBase SelectedOperation
49 return selectedOperation
;
55 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("value");
57 selectedOperation
= value;
58 SelectServiceOperation(value);
62 public void AddServiceOperation(OperationInfoBase operationInfo
, Activity implementingActivity
)
64 if (operationInfo
== null)
66 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("operationInfo");
69 TypedOperationInfo typedOperationInfo
= operationInfo
as TypedOperationInfo
;
70 OperationInfo workflowOperationInfo
= operationInfo
as OperationInfo
;
71 string contractName
= operationInfo
.GetContractFullName(null);
72 // Do not add operation if the contractName is not valid. Not throwing here gives the user to fix
73 // a broken contract/operation by selecting a different operation from the UI.
74 if (String
.IsNullOrEmpty(contractName
))
78 ServiceContractListItem serviceContract
= this.serviceContracts
.Find(contractName
);
80 if (typedOperationInfo
!= null)
82 if (serviceContract
== null)
84 serviceContract
= new ServiceContractListItem(this.operationsListBox
);
85 serviceContract
.Validating
+= new CancelEventHandler(ServiceContractValidating
);
86 serviceContract
.Name
= contractName
;
87 serviceContract
.ContractType
= typedOperationInfo
.ContractType
;
88 serviceContract
.IsCustomContract
= false;
89 AddServiceContract(serviceContract
);
92 TypedServiceOperationListItem operationItem
= new TypedServiceOperationListItem();
93 operationItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
94 operationItem
.Name
= typedOperationInfo
.Name
;
95 operationItem
.Operation
= typedOperationInfo
;
97 operationItem
.ImplementingActivities
.Add(implementingActivity
);
98 serviceContract
.AddOperation(operationItem
);
100 else if (workflowOperationInfo
!= null)
102 if (serviceContract
== null)
104 serviceContract
= new ServiceContractListItem(this.operationsListBox
);
105 serviceContract
.Validating
+= new CancelEventHandler(ServiceContractValidating
);
106 serviceContract
.Name
= workflowOperationInfo
.ContractName
;
107 serviceContract
.IsCustomContract
= true;
108 AddServiceContract(serviceContract
);
110 WorkflowServiceOperationListItem workflowOperationItem
= new WorkflowServiceOperationListItem();
111 workflowOperationItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
112 workflowOperationItem
.Operation
= workflowOperationInfo
;
113 workflowOperationItem
.ImplementingActivities
.Add(implementingActivity
);
114 serviceContract
.AddOperation(workflowOperationItem
);
119 protected override void OnHelpButtonClicked(CancelEventArgs e
)
125 protected override void OnHelpRequested(HelpEventArgs e
)
131 private void AddHelpListItem()
133 if (this.operationsListBox
.Items
.Count
== 0)
135 this.operationsListBox
.Items
.Add(new HelpListItem());
139 private void addOperationButton_Click(object sender
, EventArgs e
)
141 ServiceContractListItem serviceContractListItem
= this.operationsListBox
.SelectedItem
as ServiceContractListItem
;
142 Fx
.Assert(serviceContractListItem
!= null, "service contract list item cannot be null");
143 Fx
.Assert(serviceContractListItem
.IsCustomContract
, " this should work only on a custom contract item");
144 WorkflowServiceOperationListItem newWorkflowServiceOperationListItem
= serviceContractListItem
.CreateOperation();
145 newWorkflowServiceOperationListItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
146 this.AddServiceOperation(newWorkflowServiceOperationListItem
);
147 serviceContractListItem
.SelectionOperation(newWorkflowServiceOperationListItem
);
150 private void AddServiceContract(ServiceContractListItem serviceContractListItem
)
152 String key
= serviceContractListItem
.Name
;
153 if (this.serviceContracts
.Find(key
) == null)
155 RemoveHelpListItem();
156 serviceContracts
.Add(serviceContractListItem
);
157 operationsListBox
.Items
.Add(serviceContractListItem
);
160 private void AddServiceOperation(ServiceOperationListItem serviceOperation
)
162 if (serviceOperation
== null)
164 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperArgumentNull("serviceOperation");
166 String key
= serviceOperation
.ContractName
;
167 ServiceContractListItem serviceContract
= this.serviceContracts
.Find(key
);
168 serviceContract
.AddOperation(serviceOperation
);
169 serviceContract
.SelectionOperation(serviceOperation
);
172 private void cancelButton_Click(object sender
, EventArgs e
)
174 this.DialogResult
= DialogResult
.Cancel
;
178 private void GetHelp()
180 DesignerHelpers
.ShowHelpFromKeyword(this.serviceProvider
, typeof(OperationPickerDialog
).FullName
+ ".UI");
182 private List
<MethodInfo
> GetMethodsFromInterface(Type serviceContractInterfaceType
)
184 List
<MethodInfo
> methodInfos
= new List
<MethodInfo
>();
185 Queue
<Type
> interfacesQueue
= new Queue
<Type
>();
186 List
<Type
> interfacesList
= new List
<Type
>();
187 interfacesQueue
.Enqueue(serviceContractInterfaceType
);
189 while (interfacesQueue
.Count
> 0)
191 Type currentInterfaceType
= interfacesQueue
.Dequeue();
192 interfacesList
.Add(currentInterfaceType
);
193 foreach (Type baseInteface
in currentInterfaceType
.GetInterfaces())
195 if (!interfacesList
.Contains(baseInteface
))
197 interfacesQueue
.Enqueue(baseInteface
);
200 methodInfos
.AddRange(currentInterfaceType
.GetMethods());
205 private void ImportContract(Type serviceContractType
)
208 foreach (MethodInfo methodInfo
in GetMethodsFromInterface(serviceContractType
))
210 if (!ServiceOperationHelpers
.IsValidServiceOperation(methodInfo
))
214 TypedServiceOperationListItem operationItem
= new TypedServiceOperationListItem();
215 operationItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
216 operationItem
.Name
= ServiceOperationHelpers
.GetOperationName(this.serviceProvider
, methodInfo
);
217 operationItem
.Operation
.ContractType
= serviceContractType
;
218 operationItem
.Operation
.Name
= ServiceOperationHelpers
.GetOperationName(this.serviceProvider
, methodInfo
);
219 this.AddServiceOperation(operationItem
);
223 void ImportContractButtonClicked(object sender
, EventArgs e
)
225 using (TypeBrowserDialog typeBrowserDialog
= new TypeBrowserDialog(serviceProvider
as IServiceProvider
, new ServiceContractsTypeFilterProvider(), "System.String"))
227 typeBrowserDialog
.ShowDialog();
228 if (typeBrowserDialog
.SelectedType
!= null)
230 ServiceContractListItem contractItem
= new ServiceContractListItem(this.operationsListBox
);
231 contractItem
.Validating
+= new CancelEventHandler(ServiceContractValidating
);
232 contractItem
.Name
= typeBrowserDialog
.SelectedType
.FullName
;
233 contractItem
.ContractType
= typeBrowserDialog
.SelectedType
;
234 contractItem
.IsCustomContract
= false;
235 CancelEventArgs cancelEventArgs
= new CancelEventArgs();
236 contractItem
.Validating
.Invoke(contractItem
, cancelEventArgs
);
237 if (cancelEventArgs
.Cancel
)
241 AddServiceContract(contractItem
);
243 ImportContract(typeBrowserDialog
.SelectedType
);
248 void NewContractButtonClicked(object sender
, EventArgs e
)
250 ServiceContractListItem contractItem
= this.serviceContracts
.CreateWithUniqueName();
251 contractItem
.Validating
+= new CancelEventHandler(ServiceContractValidating
);
252 contractItem
.IsCustomContract
= true;
253 this.AddServiceContract(contractItem
);
254 WorkflowServiceOperationListItem newWorkflowServiceOperationListItem
= contractItem
.CreateOperation();
255 newWorkflowServiceOperationListItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
256 this.AddServiceOperation(newWorkflowServiceOperationListItem
);
257 contractItem
.SelectionOperation(newWorkflowServiceOperationListItem
);
260 private void okButton_Click(object sender
, EventArgs e
)
262 object selectedObject
= operationsListBox
.SelectedItem
;
263 if (selectedObject
== null)
265 selectedOperation
= null;
267 if (selectedObject
is TypedServiceOperationListItem
)
269 selectedOperation
= ((TypedServiceOperationListItem
) selectedObject
).Operation
;
271 else if (selectedObject
is WorkflowServiceOperationListItem
)
273 selectedOperation
= ((WorkflowServiceOperationListItem
) selectedObject
).Operation
;
277 // dont close the dialog when contracts are selected
280 this.DialogResult
= DialogResult
.OK
;
284 private void OperationPickerDialogLoad(object sender
, EventArgs e
)
286 if (this.serviceContracts
.Count
== 0)
290 foreach (ServiceContractListItem serviceContractListItem
in this.serviceContracts
)
292 if (!serviceContractListItem
.IsCustomContract
)
294 ImportContract(serviceContractListItem
.ContractType
);
297 this.importContractButton
.Click
+= new EventHandler(ImportContractButtonClicked
);
298 this.operationsListBox
.DoubleClick
+= new EventHandler(operationsListBox_DoubleClick
);
299 this.operationsListBox
.SelectedIndexChanged
+= new EventHandler(operationsListBox_SelectedIndexChanged
);
300 this.addOperationButton
.Click
+= new EventHandler(addOperationButton_Click
);
301 this.toolStripButton1
.Click
+= new EventHandler(NewContractButtonClicked
);
302 this.okButton
.Click
+= new EventHandler(okButton_Click
);
305 // This is to make the selected operation the selected item in the operationsListBox.
306 // This needs to be done to work around the Microsoft bug causing selection events to not fire till form is loaded.
307 if (this.selectedOperation
!= null)
309 SelectServiceOperation(this.selectedOperation
);
311 else // select the first operation if no selectedoperation is set
313 if (operationsListBox
.Items
.Count
> 0)
315 operationsListBox
.SetSelected(0, true);
321 void operationsListBox_DoubleClick(object sender
, EventArgs e
)
323 okButton_Click(sender
, e
);
326 private void operationsListBox_SelectedIndexChanged(object sender
, EventArgs e
)
328 if (operationsListBox
.SelectedItemViewControl
!= null)
330 this.addOperationButton
.Visible
= false;
331 detailsViewPanel
.Visible
= false;
332 // Give the old details control a chance to valiadte its fields before tearing it down.
333 foreach (Control control
in detailsViewPanel
.Controls
)
335 UserControl userControl
= control
as UserControl
;
336 if (userControl
!= null)
338 userControl
.ValidateChildren();
341 detailsViewPanel
.Controls
.Clear();
342 operationsListBox
.SelectedItemViewControl
.Dock
= DockStyle
.Fill
;
343 detailsViewPanel
.Controls
.Add(operationsListBox
.SelectedItemViewControl
);
344 detailsViewPanel
.Visible
= true;
345 if (operationsListBox
.SelectedItem
is ServiceOperationListItem
)
347 this.okButton
.Enabled
= true;
351 this.okButton
.Enabled
= false;
352 ServiceContractListItem serviceContractListItem
= this.operationsListBox
.SelectedItem
as ServiceContractListItem
;
353 if ((serviceContractListItem
!= null) && (serviceContractListItem
.IsCustomContract
))
355 this.addOperationButton
.Visible
= true;
362 private void RemoveHelpListItem()
364 if (this.operationsListBox
.Items
.Count
> 0 && this.operationsListBox
.Items
[0] is HelpListItem
)
366 this.operationsListBox
.Items
.Clear();
370 private void SelectServiceOperation(OperationInfoBase operationInfo
)
372 Fx
.Assert(operationInfo
!= null, "operationInfo cannot be null");
373 ServiceContractListItem serviceContract
= this.serviceContracts
.Find(operationInfo
.GetContractFullName(null));
374 // Dont select operation if the contract cannot be found in the serviceContracts list
375 if (serviceContract
== null)
379 ServiceOperationListItem operationItem
= null;
380 if (operationInfo
is OperationInfo
)
382 operationItem
= new WorkflowServiceOperationListItem();
383 operationItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
385 operationItem
.Name
= operationInfo
.Name
;
386 ((WorkflowServiceOperationListItem
) operationItem
).Operation
= operationInfo
as OperationInfo
;
389 else if (operationInfo
is TypedOperationInfo
)
391 operationItem
= new TypedServiceOperationListItem();
392 operationItem
.Validating
+= new CancelEventHandler(ServiceOperationValidating
);
393 operationItem
.Name
= operationInfo
.Name
;
394 ((TypedServiceOperationListItem
) operationItem
).Operation
= operationInfo
as TypedOperationInfo
;
397 serviceContract
.SelectionOperation(operationItem
);
400 void ServiceContractValidating(object sender
, CancelEventArgs e
)
402 ServiceContractListItem serviceContractListItem
= (ServiceContractListItem
) sender
;
404 if (string.IsNullOrEmpty(serviceContractListItem
.Name
))
407 string errorString
= SR2
.GetString(SR2
.ContractNameCannotBeEmpty
);
408 DesignerHelpers
.ShowMessage(this.serviceProvider
, errorString
, System
.Workflow
.ComponentModel
.Design
.DR
.GetString(System
.Workflow
.ComponentModel
.Design
.DR
.WorkflowDesignerTitle
), MessageBoxButtons
.OK
,
409 MessageBoxIcon
.Error
, MessageBoxDefaultButton
.Button1
);
412 bool duplicatesFound
= false;
413 foreach (ServiceContractListItem foundContract
in serviceContracts
)
415 if (foundContract
== serviceContractListItem
)
420 // allow reimport of existing imported contracts
421 if (!serviceContractListItem
.IsCustomContract
&& serviceContractListItem
.ContractType
.Equals(foundContract
.ContractType
))
426 if (foundContract
.Name
.Equals(serviceContractListItem
.Name
))
428 duplicatesFound
= true;
433 // contract names must be unique
438 string errorString
= SR2
.GetString(SR2
.ContractNameMustBeUnique
);
439 DesignerHelpers
.ShowMessage(this.serviceProvider
, errorString
, System
.Workflow
.ComponentModel
.Design
.DR
.GetString(System
.Workflow
.ComponentModel
.Design
.DR
.WorkflowDesignerTitle
), MessageBoxButtons
.OK
,
440 MessageBoxIcon
.Error
, MessageBoxDefaultButton
.Button1
);
448 void ServiceOperationValidating(object sender
, CancelEventArgs e
)
451 ServiceOperationListItem serviceOperationListItem
= (ServiceOperationListItem
) sender
;
452 string newOperationName
= serviceOperationListItem
.Name
;
453 string contractName
= serviceOperationListItem
.ContractName
;
454 if (string.IsNullOrEmpty(newOperationName
))
457 string errorString
= SR2
.GetString(SR2
.OperationNameCannotBeEmpty
);
458 DesignerHelpers
.ShowMessage(this.serviceProvider
, errorString
, System
.Workflow
.ComponentModel
.Design
.DR
.GetString(System
.Workflow
.ComponentModel
.Design
.DR
.WorkflowDesignerTitle
), MessageBoxButtons
.OK
,
459 MessageBoxIcon
.Error
, MessageBoxDefaultButton
.Button1
);
462 Fx
.Assert(!string.IsNullOrEmpty(contractName
), "contract name should be valid to run this check");
463 ServiceContractListItem contractListItem
= serviceContracts
.Find(contractName
);
464 Fx
.Assert(contractListItem
!= null, "contract should be present in the list to run this check");
466 // operation names must be unique inside a contract
467 bool duplicatesFound
= false;
468 foreach (ServiceOperationListItem foundOperation
in contractListItem
.Operations
)
470 if (foundOperation
== serviceOperationListItem
)
474 if (foundOperation
.Name
.Equals(newOperationName
))
476 duplicatesFound
= true;
485 string errorString
= SR2
.GetString(SR2
.OperationNameMustBeUnique
);
486 DesignerHelpers
.ShowMessage(this.serviceProvider
, errorString
, System
.Workflow
.ComponentModel
.Design
.DR
.GetString(System
.Workflow
.ComponentModel
.Design
.DR
.WorkflowDesignerTitle
), MessageBoxButtons
.OK
,
487 MessageBoxIcon
.Error
, MessageBoxDefaultButton
.Button1
);
493 [ListItemView(typeof(HelpListItemViewControl
))]
494 [ListItemDetailView(typeof(ListItemViewControl
))]
495 private class HelpListItem
499 private class HelpListItemViewControl
: ListItemViewControl
502 protected override void OnLoad(EventArgs e
)
504 this.Width
= this.Parent
.Width
- 10;
505 Label label
= new Label();
506 label
.ForeColor
= System
.Drawing
.SystemColors
.GrayText
;
507 label
.Dock
= DockStyle
.Fill
;
508 this.Font
= new Font(this.Font
, FontStyle
.Italic
);
509 label
.Text
= SR2
.GetString(SR2
.AddOperationsUsingImportAddButtons
);
510 this.Controls
.Add(label
);
514 private class ServiceContractsTypeFilterProvider
: ITypeFilterProvider
517 string ITypeFilterProvider
.FilterDescription
519 get { return SR2.GetString(SR2.ChooseAServiceContractFromBelow); }
521 bool ITypeFilterProvider
.CanFilterType(Type type
, bool throwOnError
)
523 if (!type
.IsInterface
)
527 if (type
.IsDefined(typeof(ServiceContractAttribute
), true))