InfoPath Context Sensitive Help


InfoPath SP1 (public beta at the link; final due out this summer) includes a lot of cool changes, both in the UI and behind the scenes (most notably the ability to stuff managed code behind the form). First I’m going to cover the OnContextChange event and using it to create context-sensitive help.


To create a managed code InfoPath form, you need to download the InfoPath Toolkit for Visual Studio .Net – this provides the templates for InfoPath in VS. Once installed, open Visual Studio, create a new project, select Microsoft Office InfoPath Projects, then either “Visual Basic Projects” or “Visual C# Projects” (I’ll be using C#), and “InfoPath Form Template” from the “Templates” pane.


Name your project, click “OK” and you’ve got an InfoPath project and form. (Also notice that under the “Project” menu in Visual Studio you’ve got some new InfoPath commands, most notably “Open InfoPath” for those times you close the form designer)


So, for our context-sensitive help we’re going to need an HTML file containing the help. Create your file – all you really need to do is append all the help paragraphs/articles into a single file. The way I handled context sensitivity is to wrap each help segment into a DIV, then hide all the DIVs and show the appropriate DIV based on the control selected. Other possibilities include using HTML anchors and scrolling to the anchor for the article, or even creating a document with an empty DIV, then pulling the text from another location and dynamically inserting it into the document.


So, I have an HTML document with a series of DIVs. I used FrontPage 2003 because I found the layer handling helped out a lot. (View | Task Pane, then in the Task Pane menu at the top select “Layers”) You’ll want each layer/DIV to use the following tag:


<div style=”position: absolute; visibility: hidden; left: 0px; top: 0px” id=”[Name]”>


For [Name] use the control name for the control you want the DIV associated with.


[Thanks to Josh Bertsch for help with the following code, C# and jscript]


Now add the following jscript to the <HEAD> of the file:


<script>
 var g_anchor=””;
 function waitForContext(anchor)
 {
  g_anchor=anchor;
  window.setTimeout(“setTaskPaneLoc();”, 1000);
 }
 
 function setTaskPaneLoc(aLoc)
 {
  var aLoc=g_anchor;
  var aCol=document.all.tags(“DIV”);
  var aColLen=aCol.length;
  
  var anchorNames=””;
  
  for(var i=0; i<aColLen; i++)
  {
   anchorNames+=aCol[i].id + “; “;
   if(aCol[i].id==aLoc)
   {
    aCol[i].style.visibility=”visible”;
   }
   else
   {
    aCol[i].style.visibility=”hidden”;
   }
  }
 }
</script>


This will, after a 1-second pause, zip through the DIV tags in the file, showing the one whose ID is the same as the control name, and hiding the rest.


Once you’re happy with the file, in InfoPath go to Tools | Form Options, then the Advanced tab. In the “Custom Task Pane“ section check “Enable custom task pane”, then click the “Resource Files“ button and add your file. (NOTE: if you change your help file later, you’ll have to go to this option, remove the file and add it again, otherwise you won’t see your changes). Once you’ve added the file, then it should be available in the drop-down for “Task pane location“ – select it.


Now, in InfoPath go to the Tools Menu, Programming, and click “On Context Change Event“ – this will create and take you to the OnContextChange event handler in the VS.Net IDE.


Add a reference in the project to Microsoft.mshtml.


Use this code in your OnContextChange handler:


if (e.Type == “ContextNode”)


{



string aLoc=e.Context.nodeName;


aLoc=aLoc.Replace(“my:”, “”);


HTMLTaskPaneObject taskPane=(HTMLTaskPaneObject)thisXDocument.View.Window.TaskPanes[0];


mshtml.HTMLWindow2Class window=(mshtml.HTMLWindow2Class)taskPane.HTMLDocument.Script;


window.execScript(“waitForContext(‘” + aLoc + “‘)”, “JScript”);


}


That should do it – now just remember that the DIV id has to be the same as the name of the control. Also watch out for width/height definitions on the DIVs – best to just let the task pane do the formatting.


Philo

Comments (4)

  1. I am trying to make a html help file for my app. I saw that you know this and thought maybe you can help because I am clueless. Using VB 6 and Html Help Workshop, I am trying to add context sensitive help with pages hosted on a web server. The context sensitive help works for the files in the .chm file, but for those online, it jumps to the topic, but in the navigation pane, but the content area doesnt load the online document. I am thinking, I can’t be the only one wanting to do this. You think you can help me?

  2. Keith says:

    Hey Philo,

    Nice post – exactly the info I was after. I had to make some slight changes to get it to work on my machine though. I don’t seem to have a HtmlTaskPane.Script property (I can however use HtmlTaskPane.Scripts.Item(0) so no dramas there). I wasn’t able to do this cast though:

    mshtml.HTMLWindow2Class window=(mshtml.HTMLWindow2Class)taskPane.HTMLDocument.Script;

    Seems the object model you have and the one I have are slightly different 🙂 The code that eventually worked for me was:

    If e.Type = "ContextNode" Then

    Dim aLoc As String = e.Context.nodeName

    aLoc = aLoc.Replace("my:", "")

    Dim taskPane As HTMLTaskPaneObject = CType(thisXDocument.View.Window.TaskPanes(0), HTMLTaskPaneObject)

    taskPane.HTMLDocument.scripts.item()

    taskPane.HTMLWindow.execScript("waitForContext(‘" & aLoc & "’)", "JScript")

    End If

  3. Keith says:

    Oops, left in an errant taskPane.HTMLDocument.scripts.item() from when I was poking around the object model in intellisense so ignore that.