Introduction
This is an attempt to solve one of the common issues related to Infopath View Switching when it is hosted on an Infopath FormControl
.
Background
I believe that there are not many developers who are experimenting with Infopath FormControl
. If you are, then you might have experienced issues with Switching Views and Printing Infopath views consecutively inside a method. From the surface, this looks simple.
for (int viewIndex = 0; viewIndex < formControl1.XmlForm.ViewInfos.Count; viewIndex++)
{
ViewInfo viewInfo = formControl1.XmlForm.ViewInfos[viewIndex];
formControl1.XmlForm.ViewInfos.SwitchView(viewInfo.Name);
}
But when you try this in your code, you will get the following COM Exception:
{"InfoPath cannot execute any view-related object model calls. The view is not ready."}
The error message says the view is not ready, the view is still switching so my next attempt was delaying the Next switch via a Sleep. I tried that. No matter how much delay I provide, this simply won't work.
Yes, it's nasty when you are almost finished your project and this is only one functionality which blocks your release. I was playing with it and found a workaround to switch and Print Infopath pages on the fly. You have to go an extra mile to make this work.
Using the Code
FormControl
’s ContextChanged
event is useful in this situation. The contextChanged
event is asynchronous. It does not fire on every change on the context node; instead it fires after the application has stopped processing other events.
So tie to the FormEvents_ContextChanged
event in the InternalStartup
event of the form. ( FormEvents_ContextChanged
event triggers when the SwitchView
method, switches and gets focus on the first control of the form. I believe that’s the last event trigger as far as switching views is considered.)
To trigger to the next view, I am using the famous signal mechanism. From the Context changed event handler, I am signalling the Form Control to switch to the next view. That seems simple, but once I finished coding, this it would not do the desired job unless I used two different BeginInvoke
s which do the signalling properly.
First - call the PrintFrom
a BeginInvoke
call:
PrintInvokerDelegate del = PrintInvoker;
del.BeginInvoke(null, null);
Next - Call your SwitchViewDelegate
from another thread:
BeginInvoke(new SwitchViewDelegate(SwitchView), new object[] {viewIndex});
m_ar.WaitOne(3600, false);
And the AutoResetEvent
waits here for the signal from ContextChanged
Event handler.
Also make sure to Print the First View without the above steps since ContextChanged
event won't fire if you are switching to the same view.
Save papers by testing the app by changing the Print Code to ExporttoPDf
(you may want to install the Microsoft Plugin for this).
Happy Switching now...
History
- 24th December, 2008: Initial post