|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
WF ActivityValidator: checking if DependencyProperty has been bounI have a custom activity that has a DependencyProperty. The property type is a complex object (just an object with some properties, nothing fancy). When I drag my custom activity onto a workflow I want to ensure the property is bound to a field in the workflow. Solution: I’ve created a custom ActivityValidator to validate the activity. This works fine for the other DependencyProperty’s that are simple types (e.g. strings). Problem My custom validator wont seem to work for the DependencyProperty that contains a complex object. Hers my custom validator public class UpdatePaymentActivityValidator : ActivityValidator { public override ValidationErrorCollection Validate(ValidationManager manager, object obj) { UpdatePaymentActivity updatePaymentActivity = obj as UpdatePaymentActivity; ValidationErrorCollection validationErrors = new ValidationErrorCollection(); if (updatePaymentActivity == null) { throw new InvalidOperationException("Parameter obj is not of type : " + typeof(UpdatePaymentActivity).ToString()); } Activity parent = updatePaymentActivity.Parent; if (parent != null) { // this validates OK if (String.IsNullOrEmpty(updatePaymentActivity.Message)) { validationErrors.Add(new ValidationError("Property Message is not set.", 1)); } // this next line always fails because Payment is always null. // Payment is a DependencyProperty on the activity and is a complex object if (updatePaymentActivity.Payment == null) { validationErrors.Add(new ValidationError("Property Payment is not set.", 1)); } } return validationErrors; } } The comment in the code indicates the like that always returns null. I can understand that the value for Payment is going to be null, its not set until runtime... but how do I check that its bound in the designer to a field in the workflow? Perhaps by directly accessing something on the static DependencyProperty of the activity?? Or do I have to create a validator for the workflow that checks it? What am I missing here? Hello Keith,
I understand that you are using the Validator to valid the Activity in Workflow design. Based on my research, if you did not bound the Property to a field that means the Property will be null and you could not compile the project and the project will indicate a validation error. So you do not need to concern about the unbound property because it will be compiled. Sincerely, Wei Lu Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. "if you did not bound the Property to a field that
means the Property will be null and you could not compile the project and the project will indicate a validation error" problem is I am binding the property but the validator still sees it as null. Do this as a test: create a workflow console application and add the following. A customer class: -------------------- public class Customer { private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; } } private string _lastName; public string LastName { get { return _lastName; } set { _lastName = value; } } } An activity: -------------------- [ToolboxItem(typeof(ActivityToolboxItem))] [Designer(typeof(ActivityDesigner), typeof(IDesigner))] [ActivityValidator(typeof(WriteCustomerNameToConsoleActivityValidator))] public class WriteCustomerNameToConsoleActivity : Activity { public static DependencyProperty CustomerProperty = System.Workflow.ComponentModel.DependencyProperty.Register("Customer", typeof(Customer), typeof(WriteCustomerNameToConsoleActivity)); [Description("")] [Category("")] [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public Customer Customer { get { return ((Customer)(base.GetValue(WriteCustomerNameToConsoleActivity.CustomerProperty))); } set { base.SetValue(WriteCustomerNameToConsoleActivity.CustomerProperty, value); } } public static DependencyProperty SimpleStringProperty = System.Workflow.ComponentModel.DependencyProperty.Register("SimpleString", typeof(String), typeof(WriteCustomerNameToConsoleActivity)); [Description("")] [Category("")] [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public String SimpleString { get { return ((String)(base.GetValue(WriteCustomerNameToConsoleActivity.SimpleStringProperty))); } set { base.SetValue(WriteCustomerNameToConsoleActivity.SimpleStringProperty, value); } } protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { Console.WriteLine("Customers name: '{0} {1}'", Customer.FirstName, Customer.LastName); Console.WriteLine("SimpleString : '{0}'", SimpleString); return ActivityExecutionStatus.Closed; } } An activity validator: -------------------- public class WriteCustomerNameToConsoleActivityValidator : ActivityValidator { public override ValidationErrorCollection Validate(ValidationManager manager, object obj) { WriteCustomerNameToConsoleActivity writeCustomerNameToConsoleActivity = obj as WriteCustomerNameToConsoleActivity; ValidationErrorCollection validationErrors = new ValidationErrorCollection(); if (writeCustomerNameToConsoleActivity == null) { throw new InvalidOperationException("Parameter obj is not of type : " + typeof(WriteCustomerNameToConsoleActivity).ToString()); } Activity parent = writeCustomerNameToConsoleActivity.Parent; if (parent != null) { if (writeCustomerNameToConsoleActivity.Customer == null) validationErrors.Add(new ValidationError("Property Customer is not set.", 1)); if (String.IsNullOrEmpty(writeCustomerNameToConsoleActivity.SimpleString)) validationErrors.Add(new ValidationError("Property SimpleString is not set.", 1)); } return validationErrors; } } -------------------- A sequential workflow: public sealed partial class Workflow1: SequentialWorkflowActivity { private Customer _customer; public Customer Customer { get { return _customer; } set { _customer = value; } } public Workflow1() { InitializeComponent(); _customer = new Customer(); _customer.FirstName = "Keith"; _customer.LastName = "Woods"; } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> [System.Diagnostics.DebuggerNonUserCode] private void InitializeComponent() { this.CanModifyActivities = true; this.writeCustomerNameToConsoleActivity1 = new WorkflowConsoleApplication5.WriteCustomerNameToConsoleActivity(); // // writeCustomerNameToConsoleActivity1 // this.writeCustomerNameToConsoleActivity1.Name = "writeCustomerNameToConsoleActivity1"; // // Workflow1 // this.Activities.Add(this.writeCustomerNameToConsoleActivity1); this.Name = "Workflow1"; this.CanModifyActivities = false; } private WriteCustomerNameToConsoleActivity writeCustomerNameToConsoleActivity1; } Try compile it, you should get 2 errors because you have not bound the activities customer and SimpleString properties. So in the workflow designer for the above workflow click on the activity and select proeprties. Now add a value for the SimpleString. Try compile agains, now only 1 error. Now bind the activites customer property to the Customer property that hands of the workflow and compile again. The validator still sees the customer as null. Like I was mentioning before I can understand that the value for Payment is going to be null, its not set until runtime... but how do I check that its bound in the designer to a field in the workflow? Hello Keith,
I would like to know if you assign your propertys to a value in the code, could you compile the project? Sincerely, Wei Lu Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. > I would like to know if you assign your propertys to a value in the code, What exactly do you mean? The property 'Customer' in the example before gets assigned at runtime. In my example that happens in the workflow constructor: public Workflow1() { InitializeComponent(); _customer = new Customer(); _customer.FirstName = "Keith"; _customer.LastName = "Woods"; } > could you compile the project? No because even thought I've bound the Customer property on the activity to the Custom property on the workflow the customer is still set to null at the time the activity validates: if (writeCustomerNameToConsoleActivity.Customer == null) validationErrors.Add(new ValidationError("Property Customer is not set.", 1)); Show quote "Wei Lu [MSFT]" wrote: > Hello Keith, > > I would like to know if you assign your propertys to a value in the code, > could you compile the project? > > Sincerely, > > Wei Lu > Microsoft Online Community Support > > ================================================== > > When responding to posts, please "Reply to Group" via your newsreader so > that others may learn and benefit from your issue. > > ================================================== > This posting is provided "AS IS" with no warranties, and confers no rights. > > Hello Keith,
I did reproduce this issue. I am consulting internally for some advice. I appreciate your patience. Sincerely, Wei Lu Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. Hello Keith,
I found that the main cause of this issue is that the DependcyProperty could not have a default value for the reference type data. So we could not assign a default value for the class. Thus, the dafult value for a class is null so whenever you compile the project, the validator will recognize that the property is null and so raise the error. I found that you only use the class like a structure. So I thought that the workaround is that you change your class Customer to be a structure. Since struture in .NET is value type, so we could initialize the instance. Then, in the workflow, you could bound the field to the property. Here are some sample code: using System; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Compiler; namespace WFWorkShop { public struct PersonalAmount { public int Amount; public string Name; public PersonalAmount(int intAmount, string strName) { //Constructor, initialize the structure. Amount = intAmount; Name = strName; } } [ActivityValidator(typeof(SimpleValidator))] public partial class Simple : Activity { static PersonalAmount pAmount = new PersonalAmount(50,""); public static readonly DependencyProperty PAmountProperty = DependencyProperty.Register("PAmount", typeof(PersonalAmount), typeof(Simple), new PropertyMetadata(pAmount) //Set the default value for the PAmount ); public PersonalAmount PAmount { get { return (PersonalAmount)base.GetValue(PAmountProperty); } set { base.SetValue(PAmountProperty, value); } } } public class SimpleValidator : ActivityValidator { public override ValidationErrorCollection Validate( ValidationManager manager, object obj) { ValidationErrorCollection errors = base.Validate(manager, obj); Simple simple = obj as Simple; if (simple.PAmount.Amount > 100 || simple.PAmount.Amount < 50) { ValidationError error = new ValidationError( "Simple.Amount must be between 50 and 100", 7000); errors.Add(error); } return errors; } } } Hope this helps! Sincerely, Wei Lu Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. Hi ,
How is everything going? Please feel free to let me know if you need any assistance. Sincerely, Wei Lu Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights. |
|||||||||||||||||||||||