When you want to pass data from a Sharepoint workflow to a task InfoPath form, the recommended method (in fact I don't know of any other one) is using a "receive data" data source, defined by the ItemMetadata.xml file. The structure of this file is documented in various places around the net, for simple data types (like, say TextBox-es or CheckBox-es). Unfortunately, when it comes to passing data to complex controls like the drop-down list
, it seems there just is a void of information, although people are in need of such a functionality. Several posts on the MSDN forums debate the issue, like this one or this one, but, although they pointed me in the right direction, they failed to give a complete and conclusive example of how to do it. So after going through the pain of getting the stuff to work, here's a step by step walkthrough that should, hopefully, spare you the "research" involved:
The overview, before going into details, is this: create some fields in the main data source to which the drop-down list will be bound, then populate these fields dinamically at runtime with data from the secondary (ItemMetadata) data source.
You might be surprised to hear that the drop-down list will read its data from the main data source (I know I was), since the first idea would be to have it get its data from the "receive data" data source (defined by the ItemMetadata.xml file). Unfortunately it sems that the ItemMetadata.xml file can't contain "complex data" (here's that word again...), just simple "rowset" data, so it's no good for populating a drop-down list (whose fields are defined by two attributes, Name and Value). So what we have to do is basically receive the data for the list in a (ONE) field of the secondary data source, then "copy" this data into the fields of the main data source. I say "copy" because since we're putting "complex" (three times now...) data into one field, there might be multiple ways to do it. I took the approach where the field will store the exact xml needed by the main data source fields, and then just replace it at form load. So without further ado, here's what you have to...umm...do:
- In the InfoPath designer, goto Data Sources and:
- add a group, let's call it "Teachers"
- in this group add a repeating field, called "Teacher"
- under Teacher add two fields, say "Name" and "DomainAccount" (these will be the display text and value of the drop-down list entries)
- In your drop-down list properties select "look up values in the form's data source" and:
- for "entries" choose the Teacher field
- for "value" choose "DomainAccount"
- for "display name" choose "Name"
- Open your ItemMetadata.xml file in some editor (Notepad?) and add a new field, for example ows_TeachersData. Be sure to update your secondary data source with the new schema, by specifying the .xml file again.
- At this point the drop-down list is set up to get its data, and its data will come in the ows_TeachersData field in the secondary data source. What we still need to do is move this data from the ows_TeachersData field to the Teachers group fields in the main data source. For this you need to have VSTA installed (you can install it from your MOSS dvd). In the form menu goto Tools -> Programming -> Loading event. This will launch VSTA and create an event handler for the form's loading event.
- In the FormEvents_Loading method, write the following code:
public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
if (this.DataSources == null)
{
return;
}
XPathNavigator xmlSource = this.DataSources["ItemMetadata"].CreateNavigator();
XPathNavigator teachers = this.MainDataSource.CreateNavigator().SelectSingleNode("/my:TeachersForm/my:Teachers", NamespaceManager);
teachers.InnerXml = xmlSource.SelectSingleNode("/z:row/@ows_TeachersData", NamespaceManager).InnerXml;
}
All that's left to do at this point is, in your workflow code, to build and populate the TeachersData field. In won't go into details as it's explained elsewhere, but the data itself should look something like: "<my:Teacher my:Name="blah" my:DomainAccount="blablah"></my:Teacher><my:Teacher my:Name="blah1" my:DomainAccount="blablah1"></my:Teacher>...etc"
As a final tip, if you first want to test your code before deploying it (which you should do, as testing it directly in Sharepoint is a pain, because of the needed iisresets and such), you can just press F5 in VSTA to debug. An essential condition here is that the form security is set to "Full Trust", as opposed to "Domain" which should be set when deploying to Sharepoint, otherwise you'll get an error when opening the form.