Using Dependency Properties

Dependency properties provide a centralized repository of a workflow's state. The DependencyObject is a hash table that stores the current values of any DependencyProperty that is applied to it.

An instance type of a dependency property can be bound to instance data, in which case the actual value is not determined until runtime. You set this type of dependency property's value to be an ActivityBind to bind to the actual value that is accessed at runtime.

ActivityBind binds an activity property to any of the following:

  • Another activity property.

  • A field.

  • A property.

  • A method.

When you are binding to an activity property, if the activity on which the binding is set (the target) is a custom activity, Windows Workflow Foundation tries to resolve the source activity starting from the target's parent activity. If the source activity is not found, Windows Workflow Foundation tries to resolve the name starting from the target activity itself. If the target activity is not a custom activity, Windows Workflow Foundation tries to resolve the source activity starting from the target activity.

A metadata type of dependency property must be set to a literal value at design time because it is immutable at runtime.

Note

Any values set in ValidationOptionAttribute are ignored for instance-based dependency properties; however, they are valid for metadata-based dependency properties.

Note

If you create an activity property whose type is derived from DependencyObject, it must be declared as a metadata dependency property or an exception is thrown by the workflow run-time engine during runtime.

When you create names for your dependency properties, you must choose unique names that are not being used for dependency properties or events in any base classes that you inherit from; otherwise, an ArgumentException is thrown during runtime. For more information about dependency properties and activity binding, see Custom Activity Binding Sample and Simple Activity Sample.

DependencyProperty Example

The following code example shows how to implement a condition using a DependencyProperty. The example shows how to add a DependencyProperty, with the correct type passed in Register.

Public Shared ExecutionConditionProperty As DependencyProperty = DependencyProperty.Register("ExecuteCondition", GetType(ActivityCondition), GetType(ActivityLibrary2.Activity1))

<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
    Public Property ExecuteCondition() As ActivityCondition
    Get
        Return CType(MyBase.GetValue(ExecutionConditionProperty), ActivityCondition)
    End Get
    Set(ByVal value As ActivityCondition)
        MyBase.SetValue(ExecutionConditionProperty, value)
    End Set
End Property
public static DependencyProperty ExecutionConditionProperty = DependencyProperty.Register("ExecutionCondition", typeof(System.Workflow.ComponentModel.ActivityCondition), typeof(ActivityLibrary2.Activity1));

[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
public System.Workflow.ComponentModel.ActivityCondition ExecutionCondition
{
    get
    {
        return ((System.Workflow.ComponentModel.ActivityCondition)(base.GetValue(ActivityLibrary2.Activity1.ExecutionConditionProperty)));
    }
    set
    {
        base.SetValue(ActivityLibrary2.Activity1.ExecutionConditionProperty, value);
    }
}

Attached Properties

In certain cases, an activity is required to register a property that can be used by other activities in a workflow. This kind of property is called an attached property, which is a specialized form of dependency property. One example of an attached property is the WhenConditionProperty that is attached to child activities of the ConditionedActivityGroup activity once they are added. You register an attached property using the RegisterAttached method of the DependencyProperty class.

An attached property is a type of a dependency property that other classes declare that can then be applied to any derived class of the DependencyObject class. The class that owns the dependency property must provide static accessor methods to get and set the value on arbitrary DependencyObject instances.

The following code shows how you can use an attached property to enable child activities of a composite activity to store unique values of a property that is defined in the parent activity.

Public NotInheritable Class CustomActivity
    Inherits CompositeActivity
    Implements IActivityEventListener(Of ActivityExecutionStatusChangedEventArgs)

    ' Declare attached property provided to the child actvities.
    Public Shared ReadOnly WhenConditionProperty As DependencyProperty = DependencyProperty.RegisterAttached("ExecuteCondition", GetType(ActivityCondition), GetType(CustomActivity), New PropertyMetadata(DependencyPropertyOptions.Metadata))

    ' Constructors
    Public Sub New()
        InitializeComponent()
    End Sub

    Public Sub New(ByVal name As String)
        MyBase.New(name)
        InitializeComponent()
    End Sub

    '**********************************************************************
    ' Get and Set accessors for the attached property WhenConditionProperty.
    '**********************************************************************
    Public Shared Function GetWhenCondition(ByVal dependencyObject As Object) As Object
        If dependencyObject Is Nothing Then
            Throw New ArgumentNullException("dependencyObject")
        End If

        Return CType(dependencyObject, DependencyObject).GetValue(WhenConditionProperty)
    End Function

    Public Shared Sub SetWhenCondition(ByVal dependencyObject As Object, ByVal value As Object)
        If dependencyObject Is Nothing Then
            Throw New ArgumentNullException("dependencyObject")
        End If
        CType(dependencyObject, DependencyObject).SetValue(WhenConditionProperty, value)
    End Sub

    Protected Overrides Function Execute(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
        ' Execute implementation omitted for clarity.
    End Function

    Public Sub OnEvent(ByVal sender As Object, ByVal e As System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs) Implements System.Workflow.ComponentModel.IActivityEventListener(Of System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs).OnEvent
        ' OnEvent implementation omitted for clarity.
    End Sub

    Private Sub EvaluateChildConditions(ByVal child As Activity, ByVal context As ActivityExecutionContext)
        Dim whenCondition As ActivityCondition = CType(child.GetValue(CustomActivity.WhenConditionProperty), ActivityCondition)
        ' ...
    End Sub
End Class
public sealed class CustomActivity : CompositeActivity, IActivityEventListener<ActivityExecutionStatusChangedEventArgs>
{
    // Declare attached property provided to the child actvities.
    public static readonly DependencyProperty WhenConditionProperty = 
        DependencyProperty.RegisterAttached("WhenCondition", typeof(ActivityCondition), typeof(CustomActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata));

    // Constructors
    public CustomActivity()
    {
    }

    public CustomActivity(string name)
        : base(name)
    {
    }

    //**********************************************************************
    // Get and Set accessors for the attached property WhenConditionProperty.
    //**********************************************************************
    public static object GetWhenCondition(object dependencyObject)
    {
        if (dependencyObject == null)
            throw new ArgumentNullException("dependencyObject");
        return (dependencyObject as DependencyObject).GetValue(WhenConditionProperty);
    }

    public static void SetWhenCondition(object dependencyObject, object value)
    {
        if (dependencyObject == null)
            throw new ArgumentNullException("dependencyObject");
        (dependencyObject as DependencyObject).SetValue(WhenConditionProperty, value);
    }

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {
        // Execute implementation omitted for clarity.
    }

    public void OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e)
    {
        // OnEvent implementation omitted for clarity.
    }

    private void EvaluateChildConditions(Activity child, ActivityExecutionContext context)
    {
            ActivityCondition whenCondition = (ActivityCondition)child.GetValue(CustomActivity.WhenConditionProperty);
            // ...
    }
}

For more information about dependency properties, see the DependencyProperty and DependencyObject classes of the System.Workflow.ComponentModel namespace in the Windows Workflow Foundation Class Library reference.

See Also

Reference

DependencyObject
DependencyProperty

Concepts

Using Activity Properties
Creating Custom Activities