One of the cool new things you can do with VSTO 2005 SE is create App-Level taskpanes for the latest two Office releases (2003, and of course 2007). The basic code to demo this during various VSTO sessions takes the following form:
CustomTaskPanes.Add(new MyCoolUserControl(), "Wow, a P4n3!");
Some of you who came to the Office Developer Events noticed that if you take the basic code used in many demos the behavior of your taskpane is not quite what you might expect. The problem? Well, besides showing the pane, also add a Ribbon customization to toggle the pane on and off. The new Ribbon button is displayed in each window, but the taskpane you've added is only shown in the primary document window. So, opening new windows using CTRL_N does show the ribbon button, but doesn't show the taskpane.
This is of course possible using the VSTO object model, but you need an extra 'window' parameter for the method call displayed above. The downside, you need to administer in which Word / Excel / PowerPoint window the taskpane is displayed, and in which windows it isn't so you can take the appropriate action (create a new pane, or display the existing invisible pane). Below you can find a special manager class which you can use to toggle panes inside each window of your Office product.
First let me show you how to use it. In the ThisAddIn class, where you'd normally create your panes, you now create an instance of the TaskPaneContainer class, which manages your panes across the various open Office windows. (The VSTOPane Type is there because of an extra using VSTOPane = Microsoft.Office.Tools.CustomTaskPane statement)
public partial class ThisAddIn
{
public TaskPaneContainer _myInfoPaneContainer = null;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
_myInfoPaneContainer = new TaskPaneContainer(
new TaskPaneContainer.TaskPaneCreationCallback(CreateNewPane));
}
VSTOPane CreateNewPane(string title, Window parent)
{
return CustomTaskPanes.Add(new MyInfoUserControl(), title, parent);
}
}
Next, add Ribbon support to your AddIn, and dump the existing OnToggleButton1 method, and replace it with the following code (I'll might update the code later to have a better experience):
public void OnToggleButton1(Office.IRibbonControl control, bool isPressed)
{
if (isPressed)
{
Globals.ThisAddIn._myInfoPaneContainer.Show("Test Pane");
}
else
{
Globals.ThisAddIn._panes.HideCurrent();
}
}
Before using it you need to understand one thing about the class. Each instance of TaskPaneContainer holds a specific type of taskpane, because it uses a callback method to create the CustomTaskPane instance. Now for that code as well (download it here):
public class TaskPaneContainer
{
public delegate VSTOPane TaskPaneCreationCallback(string title, Window window);
Dictionary<Window, VSTOPane> _panes = new Dictionary<Window, VSTOPane>();
TaskPaneCreationCallback _paneCreationCallback;
public TaskPaneContainer(TaskPaneCreationCallback paneCreationCallback)
{
_paneCreationCallback = paneCreationCallback;
}
public void Show(string title)
{
VSTOPane pane = null;
Window activeWindow = Globals.ThisAddIn.Application.ActiveWindow;
if (_panes.ContainsKey(activeWindow))
{
pane = _panes[Globals.ThisAddIn.Application.ActiveWindow];
}
else
{
pane = _paneCreationCallback(title, activeWindow);
_panes.Add(activeWindow, pane);
}
pane.Visible = true;
}
public void HideCurrent()
{
Window activeWindow = Globals.ThisAddIn.Application.ActiveWindow;
if (_panes.ContainsKey(activeWindow))
{
_panes[activeWindow].Visible = false;
}
}
}
Hope it helps!
[Edit] ps: To work correctly the code does need to do one extra thing. Clear up the dictionary of taskpanes when a window closes, otherwise a reference still exists in your user code, which is of course a bad bad thing. (and I noticed a public field, aiaiai, now where did I learn to program... :-P )