Tallan's Technology Blog

Tallan's Top Technologists Share Their Thoughts on Today's Technology Challenges

Intro into Behind the Scenes Managed Code with InfoPath

gwilliams

InfoPath is a great tool for creating simple and complex forms that can be easily managed and utilized. It is designed in such a way to try to make the process easy for non-programmers so that anyone can use the software to implement a form. This sometimes causes problems when you want to do a more complex task. I will give an example in this post and then give a little background on the tools we can use to solve these problems.
Say you want to populate a repeating section of the form using data from a database, and the contents of this repeating section will be determined by the selection from a drop down. I know what you’re thinking… this can be done solely with the tools from InfoPath. So here is the clincher, the data source you want to populate the repeating section with is not the main source, it is one of the secondary sources, thus for some reason InfoPath won’t let you filter that data. Now in my defense I will say that it could be possible to complete this with just the tools provided by InfoPath but the solution is probably convoluted and it is hard to find because I could not find any solutions on the web about after copious amount of time searching. In any case, there is what I think is an easier solution. You can write a little C# in the background based off of an ‘on change’ event of the drop down.
Before we jump into how we solve this problem directly we are going to talk a little about the XPathNavigator and XPathNodeIterator Objects. To allow you to access the XML data from a forms source InfoPath’s managed code object model members create XPathNavigator or XPathNodeIterators. To get an XPathNavigator object of a node you can do the following:

XPathNavigator myNode = this.MainDataSource.CreateNavigator().SelectSingleNode( [xpath_string], NamespaceManager);

To get an XPathNodeIterator object of a repeating section or group and to iterate through it you can use the following:

XPathNavigator myNodeIterator =  this.MainDataSource.CreateNavigator().Select([xpath_string], NamespaceManager);
while(myNodeIterator.moveNext())
{
//code here
}

This can be used to do anything with the child nodes of the repeating section. The safest way to get the xpath string of the node you are trying to access is from right clicking the on the Data source in the Data Source tab of the task pane, and selecting ‘Copy XPath’.
Once you have the XPathNavigator object you can modify the node or retrieve its contents. Two basic and very useful methods I use often are the ‘Value’ and the ‘SetValue’ which return and set the values of the nodes respectively.
The great thing about the managed code is that you can use any of your favorite libraries by referencing them. So to solve the problem introduced in the beginning, the desired data to be populated into the repeating section can be retrieved by using a secondary data source or by using a SqlConnection as you would in a C# application. For this example we are going to retrieve the names and descriptions of tasks using a SqlConnection which will grab the names and descriptions from a task table based off the month. We will have two resulting lists of strings called names and descriptions. There will be a drop down on the form called months, and based off of the month selected we want to display task names and their descriptions. Below I will show you how to put these in a repeating section named ‘Tasks’ which resides in a group named ‘RepeatingTable’. The Tasks repeating section has a ‘Name’ field and a ‘Description’ field.

//Remove anything previously in the repeating section
XPathNavigator firstNode = MainDataSource.CreateNavigator().SelectSingleNode(
        "/my:myFields/my:RepeatingTable/my:Tasks[1]",
        NamespaceManager);
XPathNavigator lastNode = MainDataSource.CreateNavigator().SelectSingleNode(
        "/my:myFields/my:RepeatingTable/my:Tasks[position()=last()]",
        NamespaceManager);
if(firstNode != null)
{
firstNode.DeleteRange(lastNode);
}

//check for valid input
String monthId = this.MainDataSource.CreateNavigator().SelectSingleNode(
               "/my:myFields/my:monthDropDown", NamespaceManager).Value;
if(monthId == null || "".Equals(monthId))
{
return;
}

//SQL Server Query
String server = /*connection string here */;

String sql = "SELECT [Name], [Description] FROM Task WHERE monthId = " + monthId + ";";
SqlConnection con = new SqlConnection(server);
SqlCommand cmd = new SqlCommand(sql, con);
cmd.CommandText = sql;
con.Open();
SqlDataReader results = cmd.ExecuteReader();

List names = new List();
List descriptions = new List();
while (results.Read())
{
names.Add((String)results["Name"]);
descriptions.Add((String)results["Description"]);
}
results.Close();
con.Close();

//Populate repeating section from sql server results
for (int i = 0; i < names.Count; ++i)
{
XmlDocument doc = new XmlDocument();

//set first field(column)
XmlNode group = doc.CreateElement("Tasks", NamespaceManager.LookupNamespace("my"));
XmlNode field = doc.CreateElement("Name", NamespaceManager.LookupNamespace("my"));
XmlNode node = group.AppendChild(field);
node.InnerText = names[i];

//set second column
field = doc.CreateElement("Description", NamespaceManager.LookupNamespace("my"));
node = group.AppendChild(field);
node.InnerText = descriptions[i];

doc.AppendChild(group);
MainDataSource.CreateNavigator().SelectSingleNode(
         "/my:myFields/my:RepeatingTable",
         this.NamespaceManager
         ).AppendChild(doc.DocumentElement.CreateNavigator());
}

From these simple examples you can easily manipulate the contents of the entire form with much more control then the tools InfoPath provides you, using a language that many already know. I gave these examples in C# but InfoPath also gives you the option to write the Managed code with VB. This can be set under the Tools > Form Options > Programming window. If you want to learn more about working with XML using the XPathNavigator class in InfoPath, this is a very good article. I plan on adding more posts summarizing different things that can be accomplished through managed code which are difficult to do strictly through the tools provided by InfoPath as I discover them.

No comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

\\\