Creating Custom Task Panes Using Visual Studio 2005 Tools for the Office System SE

Summary: The 2007 release of the Microsoft Office system introduces enhanced custom task panes that you can use to provide contextual assistance to your users. Learn how to create custom task panes with Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System. (25 printed pages)

Robert Green, MCW Technologies, LLC

October 2006

Applies to: Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System, 2007 Microsoft Office Suites, Microsoft Office Excel 2007, Microsoft Office InfoPath 2007, Microsoft Office Outlook 2007, Microsoft Office PowerPoint 2007, Microsoft Office Word 2007, Microsoft Visual Studio 2005 Tools for the Microsoft Office System

Contents

  • Custom Task Panes

  • Creating Custom Task Panes with Visual Studio Tools for Office Second Edition

  • Using the Ribbon to Display Custom Task Panes

  • Creating Data-Bound Custom Task Panes

  • Conclusion

  • Additional Resources

Custom Task Panes

Microsoft Office 2003 introduced the Document Actions task pane. A task pane is a panel that can be docked to the side of the document workspace to provide contextual assistance to users. Microsoft Office 2003 products include several task panes. Some of these task panes, such as Help and Research, are included in each of the applications. Others are specific to an application, such as New Document and New Workbook.

If you are building solutions with Microsoft Visual Studio 2005 Tools for the Microsoft Office System (also known as Visual Studio Tools for Office), you can create custom document-level task panes called "actions panes" that you can attach to Microsoft Office Word 2003 documents and Microsoft Office Excel 2003 workbooks. For example, you might create actions panes that assist users when they fill out expense reports in Excel or when they write letters to new customers in Word.

Visual Studio Tools for Office provides the actions pane control. This is a Microsoft Windows Forms control that is hosted inside the Document Actions task pane in Word and Excel. The actions pane control can contain other Windows Forms controls. To create an actions pane for a document or workbook, you create a user control that contains the user interface (UI) you want to present to users. You then add the user control to the control collection of the actions pane, so that your control appears on the Word or Excel task pane. The following code adds a user control named CalendarControl to the collection of controls belonging to the ActionsPane object.

Me.ActionsPane.Controls.Add(New CalendarControl)
this.ActionsPane.Controls.Add(new CalendarControl());

Actions panes in Office 2003 belong to a single document or workbook. You can add an actions pane to as many documents as you want. Just attach a customization assembly to each document or workbook and include code, similar to that shown above, in the customization.

The 2007 release of the Microsoft Office system expands the custom task pane model. Custom task panes are now available at the application level and at the document level. You can create an application-level custom task pane that assists users no matter what document is open. For example, you might create a custom task pane that enables users to select a regional office and insert the current time in that office into the currently open document, workbook, or slide.

Another enhancement to custom task panes is that you can have more than one open at a time.

To help you work with these new custom task panes, Visual Studio Tools for Office has released a set of tools called Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System (also know as Visual Studio 2005 Tools for Office Second Edition).

Custom task panes are available in the following applications:

  • Microsoft Office Access 2007

  • Microsoft Office Excel 2007

  • Microsoft Office InfoPath 2007

  • Microsoft Office Outlook 2007

  • Microsoft Office PowerPoint 2007

  • Microsoft Office Word 2007

NoteNote

Task panes are available in Access 2007, but Visual Studio 2005 Tools for Office Second Edition does not provide tools for creating them in Access.

Creating Custom Task Panes with Visual Studio Tools for Office Second Edition

This exercise shows you how to create an add-in for Word 2007. This add-in includes a custom task pane that enables the user to select a date from a calendar control and insert that date into a document.

To create a Word Add-in project

  1. Start Microsoft Visual Studio 2005.

  2. On the File menu, point to New, and then click Project.

  3. In the New Project dialog box, expand the Visual Basic or Visual C# node to view the project types. Then expand the Office node and select 2007 Add-ins.

  4. In the Templates pane, select Word Add-in.

  5. Type VSTOWordAddIn in the Name box and click OK.

  6. If you are using Visual Basic, in Solution Explorer, click Show All Files.

  7. In Solution Explorer, expand the References node.

Notice that Visual Studio added several Office-related references to the project. These include Microsoft.Office.Core, a reference to the Microsoft Office 12.0 Object Library, and Word, a reference to the Microsoft Word 12.0 Object Library.

Next, you add a custom user control to the project. This control contains a calendar control and is displayed in the custom task pane. Write code to insert into the document the date that is currently selected in the calendar.

To create a user control for the custom task pane

  1. On the Project menu, click Add New Item.

  2. In the Add New Item dialog box, select User Control.

  3. Type CalendarControl in the Name box, and then click Add.

  4. Set the Width and Height properties of the user control to 200.

  5. From the Toolbox, drag a MonthCalendar control onto the user control. Position the MonthCalendar control in the upper-left of the user control.

  6. In the Properties window, expand the Location property of the MonthCalendar control. Set the X and Y properties to 9.

  7. Set the MaxSelectionCount property to 1 to restrict the user to selecting one day at a time, rather than a range of dates.

  8. From the Toolbox, drag a Button control onto the user control. Position the Button control below the calendar control.

  9. Change the Text property of the button to Insert date. Widen the button so the text is visible and center the button horizontally in the user control.

  10. Double-click the button to display the Code Editor.

    If you are using C#, add the following statement to the top of the code file. (Visual Basic imports this library automatically, so there is no need to add an equivalent Imports statement.)

    using Word = Microsoft.Office.Interop.Word;
    
  11. Add the following declaration.

    Private myRange As Word.Range 
    
    private Word.Range myRange = null;
    
  12. Add the following code to the button's Click event handler to insert the selected date into the active Word document. ActiveDocument.Content is a Range object that represents the main document.

    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content
    Try
        myRange.InsertAfter( _
            MonthCalendar1.SelectionStart.ToShortDateString)
    Catch
        MessageBox.Show(
            "The information could not be added to the document")
    End Try
    
    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content;
    try
    {
        myRange.InsertAfter(
            monthCalendar1.SelectionStart.ToShortDateString());
    }
    catch
    {
        MessageBox.Show(
            "The information could not be added to the document");
    }
    

In this example, you added the user control to the project. You could also create a Windows Control Library project for the user control. This would enable you to create the control once and use it in multiple projects. If you needed to make changes later, you would need to make them in only one place.

To have the task pane appear automatically

  1. In Solution Explorer, right-click ThisAddin and then click View Code on the shortcut menu.

  2. Add the following declaration.

    Private ctpCalendar As Microsoft.Office.Tools.CustomTaskPane 
    
    private Microsoft.Office.Tools.CustomTaskPane ctpCalendar = null; 
    
  3. Add the following code to the Startup event handler to display the calendar control in a custom task pane. The code creates a new custom task pane and adds it to the collection of custom task panes that belong to this add-in. The Add method in this example takes two parameters: a control to add to the custom task pane, and the title to display on the task pane.

    By default, Microsoft Office applications do not display the custom task pane. You must set the Visible property to true for the task pane to appear.

    ctpCalendar = Me.CustomTaskPanes.Add(New CalendarControl(), _
        "Select a date")
    ctpCalendar.Visible = True 
    
    ctpCalendar = this.CustomTaskPanes.Add(new CalendarControl(), 
        "Select a date");
    ctpCalendar.Visible = true;
    
  4. Add the following code to the Shutdown event handler to remove the custom task pane from the collection of custom task panes in the add-in.

    Me.CustomTaskPanes.Remove(ctpCalendar)
    
    this.CustomTaskPanes.Remove(ctpCalendar);
    
  5. On the File menu, click Save All.

  6. On the Build menu, click Build Solution and verify that the project compiles correctly.

  7. Press F5 to run the application.

    The custom task pane is docked on the right of the document. The task pane's title is Select a date. The task pane contains a calendar control and an Insert date button.

    Figure . A calendar control displayed in a custom task pane

    Calendar control displayed in a custom task pane

  8. Select a date in the calendar control and click Insert date.

    The date is inserted into the document in the mm/dd/yyyy format.

  9. Exit Word.

You can bring your Visual Studio development skills to Office development. You can reuse existing UI elements, code, and techniques. You can copy controls from a Windows Form into a user control for use in a custom task pane. To use an existing user control, all you need to do is add that control to your project. You then write code to interact with the various Office applications and call that code from the same event handlers you work with in Windows applications.

Using the Ribbon to Display Custom Task Panes

The downloadable document 2007 Office System Document: UI Style Guide for Solutions and Add-Ins gives the following guidance:

"Task panes or dialogs do not appear automatically on document open. Only user actions should open and close task panes or dialogs. Ideally, all task panes are opened using a button on the Ribbon."

This is good advice for Office 2003 solutions and makes even more sense in solutions that use the 2007 Microsoft Office system applications, now that you can have multiple task panes open simultaneously. Imagine that a user has three add-ins loaded, each of which creates two custom task panes. The user certainly does not want six task panes open when he or she opens a document or workbook!

A better solution is to provide the user with the ability to display task panes when needed and to hide them when not needed. This exercise shows how to add a tab to the Ribbon. The tab includes a button to open and close the task pane you created earlier.

Currently, the code to display the custom task pane is in the Startup event handler. Therefore, the task pane appears automatically when the add-in runs. First, create methods to add and remove the custom task pane, then write code to call these methods when the user clicks a button on the Ribbon.

To have the task pane appear based on user action

  1. In Visual Studio, return to the ThisAddin code file.

  2. Create a method named AddCalendarTaskPane to create the custom task pane. Move the code in the Startup event handler into this method and add the code in bold to have the custom task pane dock to the left instead of the right.

    Public Sub AddCalendarTaskPane()
        ctpCalendar = Me.CustomTaskPanes.Add(New CalendarControl(), _
            "Select a date")
        ctpCalendar.DockPosition = _        Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft
        ctpCalendar.Visible = True 
    End Sub
    
    public void AddCalendarTaskPane()
    {
        ctpCalendar = this.CustomTaskPanes.Add(new CalendarControl(),
            "Select a date");
        ctpCalendar.DockPosition =        Microsoft.Office.Core.        MsoCTPDockPosition.msoCTPDockPositionLeft;
        ctpCalendar.Visible = true;
    }
    
  3. Create the following method to remove the custom task pane.

    Public Sub RemoveCalendarTaskPane()
        Me.CustomTaskPanes.Remove(ctpCalendar)
    End Sub
    
    public void RemoveCalendarTaskPane()
    {
        this.CustomTaskPanes.Remove(ctpCalendar);
    }
    
  4. Change the code in the Shutdown event handler to the following.

    RemoveCalendarTaskPane()
    
    RemoveCalendarTaskPane();
    

The Ribbon is a component of the new Office Fluent UI which replaces layered menus, toolbars, and task panes with a simpler user interface that is easier to learn and easier to use. You can customize the Ribbon by using XML and code that responds to user actions.

NoteNote

The article Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3) provides a detailed discussion of the Ribbon and customization scenarios.

Visual Studio 2005 Tools for Office Second Edition provides the Ribbon support item template. This is a class for customizing the Ribbon using XML. After you add this item to a project, you can customize the generated XML to add your own tabs and buttons to the Ribbon. You can also customize the class code that Visual Studio creates to meet the needs of your solution.

To customize the Ribbon

  1. On the Project menu, click Add New Item.

  2. In the Add New Item dialog box, select Ribbon support and then click Add.

    Two files are added to the project. Ribbon1.vb or Ribbon1.cs defines the Ribbon1 class and Ribbon1.xml contains an XML customization for the Ribbon.

  3. In Solution Explorer, right-click Ribbon1.xml and then click Open.

    The XML in this file is as follows. This XML is a template for customizing the ribbon.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">
      <ribbon>
        <tabs>
          <tab id="MyTab"
               label="My Tab">
            <group id="MyGroup"
                   label="My Group">
              <toggleButton id="toggleButton1" 
                            size="large"
                            label="My Button"
                            screentip="My Button Screentip"
                            onAction="OnToggleButton1" 
                            imageMso="HappyFace" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  4. Change the XML in the file to the following. This XML creates a new tab with the label VSTO Add-ins. The XML then defines a group, with the label Helpers, on the new tab. The group contains a button with the caption Insert date and an image of a calendar. When the user clicks the button, the code contained in the CalendarButtonClick method (shown later) runs.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">
      <ribbon>
        <tabs>
          <tab id="VSTOAddIns" label="VSTO Add-ins" >
            <group id="Group1" label="Helpers" visible ="1">
              <button id="Calendar" label="Insert date" 
               onAction="CalendarButtonClick" 
               imageMso="ContentControlDate"/>
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  5. In the Ribbon1 code file, uncomment the following code.

    Partial Public Class ThisAddIn
    
        Private ribbon As Ribbon1
    
        Protected Overrides Function RequestService(ByVal serviceGuid As Guid) As Object
            If serviceGuid = GetType(Office.IRibbonExtensibility).GUID Then
                If ribbon Is Nothing Then
                    ribbon = New Ribbon1()
                End If
                Return ribbon
            End If
    
            Return MyBase.RequestService(serviceGuid)
        End Function
    
    End Class 
    
    public partial class ThisAddIn
    {
        private Ribbon1 ribbon;
        protected override object RequestService(Guid serviceGuid)
        {
            if (serviceGuid == typeof(Office.IRibbonExtensibility).GUID)
            {
                if (ribbon == null)
                    ribbon = new Ribbon1();
                return ribbon;
            }
    
            return base.RequestService(serviceGuid);
        }
    }
    

    When your add-in loads, Office queries it to see whether it supports the IRibbonExtensibility interface. The role of the code above is to respond to that query and to return to Office the object that implements that interface. That object is the Ribbon1 class.

    <ComVisible(True)> _
        Public Class Ribbon1
        Implements Office.IRibbonExtensibility
    
    [ComVisible(true)]
    public class Ribbon1 : Office.IRibbonExtensibility
    

    Office then calls the GetCustomUI method of the Ribbon1 class. That method returns the XML that contains the Ribbon customization.

    Public Function GetCustomUI(ByVal ribbonID As String) As String _
        Implements Office.IRibbonExtensibility.GetCustomUI
        Return GetResourceText("VSTOWordAddIn.Ribbon1.xml")
    End Function
    
    public string GetCustomUI(string ribbonID)
    {
        return GetResourceText("VSTOWordAddIn.Ribbon1.xml");
    }
    

    The Build Action property for the XML file is set to Embedded Resource. Visual Studio builds the XML file into the add-in assembly. The GetResourceText method retrieves the XML and the GetCustomUI method then returns the XML to Office.

    The next several steps show how to use the Resource Designer as an alternate approach to adding resources to the project. This generates strongly typed resources that you can access using My.Resources in Visual Basic or Properties.Resources in Visual C#.

  6. On the Project menu, click VSTOWordAddIn Properties.

    The Project Designer opens.

  7. Click the Resources tab.

  8. Click the arrow associated with the Add Resource button and then click Add Existing File.

  9. In the Add existing file to resources dialog box, navigate to the current project folder.

  10. Select Ribbon1.xml and then click Open.

  11. Close the Project Designer, saving your changes if prompted.

  12. In the Ribbon1 file, change the code in the GetCustomUI method to the following to retrieve and return the Ribbon customization XML.

    Return My.Resources.Ribbon1
    
    Return Properties.Resources.Ribbon1;
    
  13. Delete the GetResourceText method. You replaced the call to this with the code above, so you no longer need this method.

In the Ribbon1.xml file, you specified that the code in the CalendarButtonClick method should run when the user clicks the Customer info button.

onAction="CalendarButtonClick" 

The final step is to add this method.

To respond to users clicking a button on the Ribbon

  1. In the Ribbon Callbacks region, locate and delete the OnToggleButton1 method. The template Ribbon XML that you replaced earlier refers to this method. You no longer need this method.

  2. Add the following declaration to the Ribbon1 class.

    Private calendarControlExists As Boolean
    
    private bool calendarControlExists;
    
  3. Add the following method to the Ribbon1 class to respond when the user clicks the Insert date button on the Ribbon. This code checks whether the custom task pane exists. If it does, the code calls the method to remove the task pane. If it does not exist, the code calls the method to add the task pane.

    Public Sub CalendarButtonClick(ByVal control As _
        Office.IRibbonControl)
        If Not calendarControlExists Then
            Globals.ThisAddIn.AddCalendarTaskPane()
        Else
            Globals.ThisAddIn.RemoveCalendarTaskPane()
        End If
        calendarControlExists = Not calendarControlExists
    End Sub
    
    public void CalendarButtonClick(Office.IRibbonControl control)
    if (!calendarControlExists)
    {
        Globals.ThisAddIn.AddCalendarTaskPane();
    }
    else
    {
        Globals.ThisAddIn.RemoveCalendarTaskPane();
    }
    calendarControlExists = !calendarControlExists;
    
    NoteNote

    An alternative approach is to create the custom task pane but not display it when Word starts. You can then change the Visible property when the user clicks the button on the Ribbon to display or hide the task pane. This approach is demonstrated in the next exercise.

  4. On the File menu, click Save All.

  5. On the Build menu, click Build Solution, and verify that the project compiles correctly.

  6. Press F5 to run the application.

    The task pane is not visible. A VSTO Add-ins tab is on the Ribbon.

  7. Click the VSTO Add-ins tab.

    The tab contains an Insert date button with a calendar icon.

    Figure . Clicking the button displays the Select a date custom task pane

    The Select a date custom task pane

  8. Click Insert date.

    The custom task pane appears, docked on the left side of the document.

  9. Select a date in the calendar control and then click Insert date.

    The date is inserted into the document in the mm/dd/yyyy format.

  10. Click Insert date.

    The task pane disappears.

  11. Exit Word.

In the first exercise, you created an add-in that displays a custom task pane that contains a calendar control. The user can select a date from the calendar and insert it into the Word document. You wrote code to display the task pane when Word starts. In this exercise, you customized the Ribbon to enable the user to display and hide the task pane by clicking a button, in accordance with the 2007 Microsoft Office system UI recommendations.

Creating Data-Bound Custom Task Panes

This exercise shows how to create a second task pane control. That control retrieves a list of customers from a database and displays them in a grid. The user can select a customer and click a button. The code that runs inserts the customer information into the active Word document. The exercise includes a button on the Ribbon to display this custom task pane.

NoteNote

This exercise uses Microsoft SQL Server 2005 Express Edition and the Northwind sample database. You can download Northwind and pubs Sample Databases for SQL Server 2000 from the Microsoft Download Center Web site.

To add a data source

  1. On the Data menu, click Add New Data Source.

    The Data Source Configuration Wizard appears.

  2. On the first page, select Database to specify where the application will get its data. Click Next.

  3. On the second page, click New Connection.

    The Add Connection dialog box appears.

  4. If the Data source box does not display Microsoft SQL Server Database File (SqlClient), click Change.

    The Change Data Source dialog box appears.

    1. Select Microsoft SQL Server Database File.

    2. Click OK.

  5. In the Add Connection dialog box, click Browse.

    The Select SQL Server Database File dialog box appears.

  6. Navigate to the folder that contains the Northwind database file. Select Northwind.mdf. Click Open.

  7. In the Add Connection dialog box, click Test Connection. After you are informed that the connection succeeded, click OK.

  8. Click OK to close the Add Connection dialog box.

  9. In the Data Source Configuration Wizard, click Next.

  10. Click No on the message that asks if you want to include the database file in your project.

  11. On the third page, leave the check box selected and click Next.

  12. On the fourth page, expand the Tables list.

  13. In the list of tables, select the Customers check box.

  14. Click Finish.

  15. On the Data menu, click Show Data Sources.

    The Data Sources window appears.

Next, create a custom task pane that displays a list of customers.

To create a user control with a data grid that is bound to data

  1. On the Project menu, click Add New Item.

  2. In the Add New Item dialog box, select User Control.

  3. Type CustomersControl in the Name box, and then click Add.

  4. From the Data Sources window, drag the Customers table onto the user control.

  5. Delete the CustomersBindingNavigator control, which is the tool strip above the data grid.

    The tool strip provides the ability to navigate from customer to customer, and the ability to add, save, or delete a customer. You are not including any of that functionality in this example, so you do not need the tool strip.

  6. Drag the data grid to the upper-left of the user control.

  7. Click the arrow that appears in the upper-right of the data grid.

    The DataGridView Tasks menu appears.

  8. Clear the check boxes for Enable Adding, Enable Editing, and Enable Deleting. The user can select a customer from the list, but will not have the ability to modify the list of customers.

  9. Click Edit Columns.

  10. In the Selected Columns list, select CustomerID.

  11. Click Remove.

  12. Remove all remaining columns except CompanyName.

  13. Set the Width property of the CompanyName column to 180.

  14. Change the HeaderText property to Customers.

  15. Click OK.

To design the user control

  1. Click the data grid to select it.

  2. Set the RowHeadersVisible property of the data grid to False.

  3. Set the Width property of the data grid to 194.

  4. Set the Height property to 365.

  5. Click the user control to select it.

  6. Set the Width property of the user control to 200.

  7. Set the Height property to 400.

  8. From the Toolbox, drag a Button control onto the user control. Position the Button control below the grid. Center the button horizontally in the user control.

  9. Change the Text property of the button to be Insert customer info. Widen the button so the text is visible.

To add code to insert data into the document

  1. Double-click an empty area of the user control to open the Code Editor.

  2. Delete the CustomersBindingNavigatorSaveItem_Click method.

    Visual Studio added this method to handle the Click event of the Save button on the tool strip you deleted. You do not need this code.

  3. Add the following code to the top of the code file.

    Imports System.Text 
    
    using Word = Microsoft.Office.Interop.Word;
    
  4. Add the following declarations.

    Private myRange As Word.Range
    Private customerInfo As StringBuilder
    Private customerRow As NorthwindDataSet.CustomersRow 
    
    private Word.Range myRange = null;
    private StringBuilder customerInfo = null;
    private NorthwindDataSet.CustomersRow customerRow;
    
  5. Add the following code to the user control's Load event handler to retrieve customer information from the database.

    Me.CustomersTableAdapter.Fill(Me.NorthwindDataSet.Customers)
    
    this.customersTableAdapter.Fill(this.northwindDataSet.Customers);
    
  6. Add the following code to the button's Click event handler to insert the selected customer's information into the active Word document. This code first gets a reference to a Range object representing the main document. It then gets a reference to the underlying data for the selected customer.

    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content
    customerRow = CType(CType( _
        Me.CustomersBindingSource.Current, DataRowView).Row, _
        NorthwindDataSet.CustomersRow)
    
    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content;
    customerRow = ((NorthwindDataSet.CustomersRow)
        (((DataRowView)(this.customersBindingSource.Current)).Row));
    
  7. Add the following code to insert the selected customer's information into the active Word document. This code builds a string containing the customer's company name, the name of the primary contact, and the customer's address. Note the use of methods such as IsContactNameNull to determine whether the various Customers table columns contain information.

    The code then inserts the string containing the customer's information into the active document.

    customerInfo = New StringBuilder()
    If customerRow.IsContactNameNull() = False Then
        customerInfo.AppendLine(customerRow.ContactName)
    End If
    customerInfo.AppendLine(customerRow.CompanyName)
    If customerRow.IsAddressNull() = False Then
        customerInfo.AppendLine(customerRow.Address)
    End If
    If customerRow.IsCityNull() = False Then
        customerInfo.Append(customerRow.City & " ")
    End If
    If customerRow.Is_RegionNull() = False Then
        customerInfo.Append(customerRow._Region & " ")
    End If
    If customerRow.IsPostalCodeNull() = False Then
        customerInfo.Append(customerRow.PostalCode)
    End If
    customerInfo.AppendLine()
    If customerRow.IsCountryNull() = False Then
        customerInfo.AppendLine(customerRow.Country)
    End If
    customerInfo.AppendLine()
    
    Try
        myRange.InsertAfter(customerInfo.ToString())
    Catch ex As Exception
        MessageBox.Show( _
            "The information could not be added to the document.")
    End Try
    
    customerInfo = new StringBuilder();
    if (customerRow.IsContactNameNull()==false)
    {
        customerInfo.AppendLine(customerRow.ContactName);
    }
    customerInfo.AppendLine(customerRow.CompanyName);
    if (customerRow.IsAddressNull()==false)
    {
        customerInfo.AppendLine(customerRow.Address);
    }
    if (customerRow.IsCityNull()==false)
    {
        customerInfo.Append(customerRow.City + " ");
    }
    if (customerRow.IsRegionNull()==false)
    {
        customerInfo.Append(customerRow.Region + " ");
    }
    if (customerRow.IsPostalCodeNull()==false)
    {
        customerInfo.Append(customerRow.PostalCode);
    }
    customerInfo.AppendLine();
    if (customerRow.IsCountryNull()==false)
    {
        customerInfo.AppendLine(customerRow.Country);
    }
    customerInfo.AppendLine();
    
    try
    {
        myRange.InsertAfter(customerInfo.ToString());
    }
    catch
    {
        MessageBox.Show(
            "The information could not be added to the document.");
    }
    

In the previous exercise, you added and removed the custom task pane when the user clicked a Ribbon button. The custom task pane contained a calendar control and so the overhead of creating and destroying the task pane repeatedly is not high. In this exercise, the custom task pane retrieves information from a database. To save resources, the database call should be made only once, so the custom task pane is added when the add-in starts. However, it is not visible to users until they click a Ribbon button. Clicking the button again hides the task pane, but does not remove it.

To have the task pane appear based on user action

  1. Return to the ThisAddIn file.

  2. Add the following declaration.

    Public ctpCustomers As Microsoft.Office.Tools.CustomTaskPane
    
    public Microsoft.Office.Tools.CustomTaskPane ctpCustomers = null;
    
  3. Add the following methods to add and remove the custom task pane.

    Public Sub AddCustomersTaskPane()
        ctpCustomers = Me.CustomTaskPanes.Add(New CustomersControl(), _
            "Select a customer")
        ctpCustomers.DockPosition = _
            Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft
    End Sub
    
    Public Sub RemoveCustomersTaskPane()
        Me.CustomTaskPanes.Remove(ctpCustomers)
    End Sub
    
    public void AddCustomersTaskPane()
    {
        ctpCustomers = this.CustomTaskPanes.Add(new CustomersControl(),
            "Select a customer");
        ctpCustomers.DockPosition = _
            Microsoft.Office.Core.
            MsoCTPDockPosition.msoCTPDockPositionLeft;
    }
    
    public void RemoveCustomersTaskPane()
    {
        this.CustomTaskPanes.Remove(ctpCustomers);
    }
    
  4. Add the following code to the Startup event handler to add the custom task pane.

    AddCustomersTaskPane()
    
    AddCustomersTaskPane();
    
  5. Add the following code to the Shutdown event handler to remove the custom task pane.

    RemoveCustomersTaskPane()
    
    RemoveCustomersTaskPane();
    
  6. In Solution Explorer, right-click Ribbon1.xml and then click Open.

  7. Add XML to the file to add a second button to the VSTO Add-ins tab on the Ribbon. The Helpers group contains a second button with the caption "Customer info" and an image of a person and address book. When the user clicks the button, the code contained in the CustomersButtonClick method (which is explained later) runs.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">
      <ribbon>
        <tabs>
          <tab id="VSTOAddIns" label="VSTO Add-ins">
            <group id="Group1" label="Helpers" visible ="1">
              <button id="Calendar" label="Insert date"
                onAction="CalendarButtonClick" 
                imageMso="ContentControlDate"/>
              <button id="Customers" label="Customer info"
                onAction="CustomersButtonClick" 
                imageMso="MailSelectNames"/>
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  8. In Solution Explorer, right-click the Ribbon1 file and then click View Code.

  9. Add the following declaration to the Ribbon1 class.

    Private customersControlVisible As Boolean 
    
    private bool customersControlVisible;
    
  10. Add the following method to the Ribbon1 class to display and hide the custom task pane when the user clicks the Customer info button.

    Public Sub CustomersButtonClick(ByVal control As _
        Office.IRibbonControl)
        If Not customersControlVisible Then
            Globals.ThisAddIn.ctpCustomers.Visible = True
        Else
            Globals.ThisAddIn.ctpCustomers.Visible = False
        End If
        customersControlVisible = Not customersControlVisible
    End Sub
    
    public void CustomersButtonClick(Office.IRibbonControl control)
    {
        if (!customersControlVisible)
        {
            Globals.ThisAddIn.ctpCustomers.Visible = true;
        }
        else
        {
            Globals.ThisAddIn.ctpCustomers.Visible = false;
        }
        customersControlVisible = !customersControlVisible;
    }
    
  11. On the File menu, click Save All.

  12. On the Build menu, click Build Solution and verify that the project compiles correctly.

To test the custom task pane

  1. Press F5 to run the application.

    The task pane is not visible. A VSTO Add-ins tab is on the Ribbon.

  2. Click the VSTO Add-ins tab.

    The tab contains the Insert date button and the Customer info button, which has an icon of a person and an address book.

  3. Click the Customer info button.

    The custom task pane is docked on the left of the document. The task pane's title is Select a customer. A data grid that contains customer names and an Insert customer info button is in the task pane.

    Figure . Clicking the Customer info button displays the Select a customer custom task pane

    The Select a customer custom task pane

  4. Select a customer in the data grid and click Insert customer info.

    The customer's company name, contact name, and address information are inserted into the document.

  5. Click Insert date.

    A second custom task pane appears. This task pane contains the calendar control you created earlier.

    Figure . You can have multiple custom task panes open at the same time

    Multiple custom task panes open at the same time

  6. Click Customer info.

    The custom task pane that contains the customer list disappears. The task pane with the calendar is still visible.

  7. Click Insert date.

    The custom task pane that contains the calendar disappears.

  8. Click Customer info.

    The custom task pane that contains the customer list reappears. There should be no noticeable delay, because the control already retrieved the customer information from the database.

  9. Exit Word.

In this exercise, you created an add-in that displays a custom task pane that contains a data grid. You populated the data grid with customer names retrieved from a database. The user can select a customer in the grid and insert that customer's information into the Word document. Because the database call should occur only once, you added the custom task pane when the add-in loaded. You then customized the Ribbon to enable the user to display and hide the task pane by clicking a button.

You also saw that Word now supports having more than one custom task pane visible at a time. This provides you with additional flexibility in UI design. The two task panes used in this article are independent, so you can provide the user the ability to use both at the same time. But, each open task pane uses screen space, which is a limited resource.

A good first step toward managing multiple custom task panes in an add-in is to provide buttons on the Ribbon to display and hide the task panes. You should also consider other alternatives. For example, you could use a tabbed interface in a custom task pane and enable the user to select the tab appropriate to a particular task. You could also provide a drop-down list for switching from one set of controls to another. Microsoft Office 2003 uses this technique in the built-in task pane.

Be aware that the user might be running multiple add-ins and that each of them may define one or more custom task panes. That provides even more reason to manage screen space effectively in your add-ins.

Conclusion

The enhancements to custom task panes introduced in the 2007 release of Microsoft Office provide you with more flexibility and power when creating solutions with Visual Studio Tools for Office. You can create custom task panes for InfoPath, Outlook, and PowerPoint, in addition to Word and Excel. You can build task panes that exist at the application level and task panes that you attach to a specific document, workbook, or slide. These additional capabilities enable you to create custom task panes that meet more of your user's requirements.

Visual Studio Tools for Office provides excellent support for custom task panes. If you used Visual Studio Tools for Office with Office 2003, you can take advantage of the new capabilities in the 2007 release of Microsoft Office by using familiar techniques.

About the Author

Robert Green is a developer, writer, and trainer, and is a senior consultant with MCW Technologies. Robert is a co-author of AppDev Visual Basic and C# courseware. Prior to joining MCW, Robert worked at Microsoft, and was the Visual Studio Tools for Office product manager.

Additional Resources

To learn more about the products and technologies mentioned or used in this article, see these resources: