So today I was in the process of refactoring some InfoPath 2010 forms for wider reuse. One of the views in the form was an “instructions” page, but rather than having all this “static” formatted text live on the form I wanted it to pull it from a SharePoint list that could then be easily edited and maintained by business users without having to modify the form.
This sounds reasonably easy, and I even already had a data source connection to the list I wanted to use, so all I had to do was add a new field to the SharePoint list as a Multi-Line Text datatype with rich text enabled. I didn’t want these instructions to load/change every time the form was opened, so my strategy was to create a rule and based on a condition (that told me the form was a new one) I would query the secondary data source and pull the rich text from SharePoint and store it in field located in my Main data source. I made sure that this new field was of the datatype “Rich Text (XHTML)” and that the actual Rich Text box control placed on the form was set to “Enable enhanced rich text…”, etc… Problem was that when I previewed the form, the text from the SharePoint list showed up, but all the formatting was stripped.
After a bit of troubleshooting I determined that the RTF formatting was indeed coming over from the SharePoint List data source, in fact if I bound a repeating table with a RTB directly to the secondary data source field it did indeed show the text formatted. Most other sources on the internet pointed at a faulty implementation of the “Set a Field’s Value…” rule action. Since in my case this is a pretty complex form and I had a code-behind (sandbox solution) I had the luxury of digging into this a bit further. What I found is that the problem is not with the Rule Action implementation because the formatting is not lost upon the call to .SetValue() (on the XPathNavigator pointing at your target field). It is actually lost when you read the value out of the .Value property (of the XPathNavigator pointing at your source field).
So I came up with a work around that appears to be working. That is instead of reading and writing these field values, if you pull the entire .InnerXML property of the source and set the target’s .InnerXML property to it, all the formatting properly comes over! Here’s a helper function that illustrates what I’m talking about:
private void CopyFieldValueByXml(DataSource sourceDatasource, string sourceXPath,
DataSource targetDatasource, string targetXPath)
XPathNavigator sourceNav = sourceDatasource.CreateNavigator();
XPathNavigator sourceField = sourceNav.SelectSingleNode(sourceXPath, NamespaceManager);
string dataXml = sourceField.InnerXml;
XPathNavigator targetNav = targetDatasource.CreateNavigator();
XPathNavigator targetField = targetNav.SelectSingleNode(targetXPath, NamespaceManager);
targetField.InnerXml = dataXml;
So now some warnings: First off, I (or you) still need to do a bit more testing on this work around because in my simple use case I only needed to pull static rich text into my document. I don’t know for sure if there will be any ill effects should we need to later go and edit this rich text within the form. Second, and more importantly, this little work around will only work if you are using a code behind (doesn’t have to be an admin form, I’m doing this with a sandbox solution). If this is the ONLY reason you are using a code behind then that’s probably a very unnecessary maintenance burden you are placing on your solution for a very small gain. I would not recommend you do this in that scenario. However, if you are in a situation like mine, where you need the code behind anyway, then have at it!