DCSIMG
How to bind WF 4.0 arguments to ExpressionTextbox in Code - Manu Cohen-Yashar's Blog

Manu Cohen-Yashar's Blog

How to bind WF 4.0 arguments to ExpressionTextbox in Code

Almost every activity has arguments. The workflow designer presents only the root activity's arguments (these are the "Workflow Arguments")

image

The activity's arguments has to be binded to ExpressionTextbox placed on the activity canvas (i.e. The Activity designer).

When your activity is static and is completely defined in xaml there is no problem to define the binding in the xaml definition of the activity designer (there are tons of examples).The question is what happens when arguments and ExpressionTextBoxes are built in code?
How can we bind dynamically created arguments with dynamically created ExpressionTextBox?

Dynamically created arguments should be placed in an Arguments collection. I like to use a dictionary so I can refer to it later by name (the key of the dictionary).

The arguments are crated in the CacheMetadata method.

string[] MyArgumentsNames = { "arg1,arg2" };

public Dictionary<string,Argument> Arguments { get; set; }

 

protected override void CacheMetadata(CodeActivityMetadata metadata)

{

  base.CacheMetadata(metadata);

  Collection<RuntimeArgument> arguments = new Collection<RuntimeArgument>();

 

  foreach (var argumentName in MyArgumentsNames)

  {

    //Create a new input argument of type string

    RuntimeArgument rtArgument =
      new RuntimeArgument("MyArgumentName",
                        typeof(string), ArgumentDirection.In);

    Arguements.Add(argumentName,
       Argument.Create(typeof(string), ArgumentDirection.In));

    metadata.Bind(Arguments[argumentName], rtArgument);

    arguments.Add(rtArgument);

   }

 

  //Set the arguments collection that has been built as part of the Activity's metadata

  metadata.SetArgumentsCollection(arguments);

}

After the argument is created it is time to bind it to a dynamically created ExpressionBox.

I wrote a little method that does exactly that. I assume the activity designer is no more than a simple grid with two columns.

public void DrawExpressionBoxOnCanvas(Grid activityGrid,

            string argumentName,Type argumentType,

            string direction, ModelItem ownerActivity)

{

   //Create a new row in the activity grid

   int rowIndex = activityGrid.RowDefinitions.Count;

   var newRow = new RowDefinition();

   activityGrid.RowDefinitions.Insert(rowIndex, newRow);

 

   //Create a text block on the grid with the argument name

   var txtBlock = new TextBlock();

   txtBlock.Uid = "txtBlock" + argumentName;

   txtBlock.Text = argumentName;

   txtBlock.Margin =

      new Thickness() { Bottom = 5, Top = 5, Left = 5, Right = 5 };

   Grid.SetColumn(txtBlock, 0);

   Grid.SetRow(txtBlock, rowIndex);

   activityGrid.Children.Add(txtBlock);

 

   //Create a new ExpressionTextBox on the activity grid

   var expressionTbx = new ExpressionTextBox();

   expressionTbx.Uid = "ExpressionBox" + argumentName;

   expressionTbx.HintText = String.Format("Enter {0}", argumentName);

   expressionTbx.ExpressionType = argumentType;

   expressionTbx.Margin =

      new Thickness() { Bottom = 5, Top = 5, Left = 5, Right = 5 };

   expressionTbx.Width = 110;

   expressionTbx.OwnerActivity = ownerActivity;

 

   // Create binding between the expression block and the activity's arguments

   var bind = new Binding();

   bind.Mode = BindingMode.TwoWay;

   bind.Converter = new ArgumentToExpressionConverter();

   bind.ConverterParameter = direction;

   bind.Path = new PropertyPath(

   String.Format("ModelItem.Arguments[{0}]", argumentName));

 

   //Out arguments require L-Value expression

   if (direction == "out")

       expressionTbx.UseLocationExpression = true;

 

   //Set the binding and Add the expression block to the grid

   expressionTbx.SetBinding(ExpressionTextBox.ExpressionProperty, bind);

   Grid.SetRow(expressionTbx, rowIndex);

   Grid.SetColumn(expressionTbx, 1);

   activityGrid.Children.Add(expressionTbx);

}

Hope this will help

Manu

Comments

In a Tale of Two Cities, what two family groups function as foils to each other? | Custom oil painting said:

Pingback from  In a Tale of Two Cities, what two family groups function as foils to each other? | Custom oil painting

# June 18, 2010 3:43 AM

Alexander said:

Hi Manu

Thank you for the valuable input.

I get this exception:

System.InvalidOperationException was unhandled by user code

 Message=The argument of type 'System.String' cannot be used.  Make sure that it is declared on an activity.

trying to get Argument value in execute :

foreach (Argument item in _arguments.Values){

     object v =item.Get(context);

}

Can you please help to resolve this ?

Thanks

# December 29, 2010 4:30 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: