In the Workflow Designer, all input provided to the workflow must be valid according to the model before the workflow can be serialized*. This has a number of implications that you see throughout the designer, like:

  • TryCatch designer – must select a non-duplicate exception before you can continue, can’t have empty rows
  • Switch<T> designer – switch cases must be unique
  • Generic activities – must close the type before serializing
  • Variables – can’t have duplicate variable names in the same scope

The other place you see this is in the type browser/type presenter/generic type picker. You must close all of your generics before we can serialize, so we require that you close all types before the type browser dialog box can be dismissed. We don’t allow free-form editing. In most cases, this is just fine since everything that you enter is guaranteed to be valid before you leave. Enforcing data validity in the place where you enter data is a good general UI design principle.

However, this leaves you in a weird spot with multi-dimensional arrays, since we use the same UI for type picking but require you to declare the array using the Array of T->Array of T->T selection pattern. For a multi-dimensional array of Int32, this serializes as the CLR type Int32[][], which is a jagged array. There is no other selection mechanism for arrays, which means impossible for you to declare a multidimensional array in the UI. That is because you can’t insert a comma when specifying the array type, and there is no check box or other UI switch that toggles between jagged array and multi-dimensional array mode.

Jagged arrays can do all of the things multi-dimensional arrays can do. Initialization is done as described on MSDN. Also, to iterate over the arrays you have to explicitly add the non-generic ForEach activity to the toolbox using the Choose Toolbox Items dialog box. You can’t use the generic ForEach<T> activity because jagged array types don’t implement the Collection(of Object) syntax.

If you hand-edit your XAML to change your Int32[][] to Int32[,], you can use variables and arguments that are typed as multi-dimensional arrays.  You will be able to initialize your variable using syntax like new Integer(,){{1,2},{3,4}}, use the variable in expressions, and everything works nicely at runtime.

Long story short, given our infrastructure, you’ll be better off using Collections instead of multi-dimensional or jagged arrays.

The type picking UI was something we spent a long time discussing. Your feedback on this UI is welcome.

*We allow invalid expressions because VisualBasicValue and VisualBasicReference have an ExpressionText property, so the underlying expression object is valid according to the model even though the ExpressionText is invalid. All invalid expressions are typed as Object.