Share via


Walkthrough: Displaying Custom Task Panes with E-Mail Messages in Outlook

This walkthrough demonstrates how to display a unique instance of a custom task pane with each e-mail message that is created or opened. Users can display or hide the custom task pane by using a button on the Ribbon of each e-mail message.

Applies to: The information in this topic applies to application-level projects for Outlook 2013 and Outlook 2010. For more information, see Features Available by Office Application and Project Type.

To display a custom task pane with multiple Explorer or Inspector windows, you must create an instance of the custom task pane for every window that is opened. For more information about the behavior of custom task panes in Outlook windows, see Custom Task Panes.

Note

This walkthrough presents the add-in code in small sections to make it easier to discuss the logic behind the code.

This walkthrough illustrates the following tasks:

  • Designing the user interface (UI) of the custom task pane.

  • Creating a custom Ribbon UI.

  • Displaying the custom Ribbon UI with e-mail messages.

  • Creating a class to manage Inspector windows and custom task panes.

  • Initializing and cleaning up resources used by the add-in.

  • Synchronizing the Ribbon toggle button with the custom task pane.

Note

Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. The Visual Studio edition that you have and the settings that you use determine these elements. For more information, see Visual Studio Settings.

Prerequisites

You need the following components to complete this walkthrough:

link to video For a related video demonstration, see How Do I: Use Task Panes in Outlook?.

Creating the Project

Custom task panes are implemented in application-level add-ins. Start by creating an add-in project for Outlook.

To create a new project

  • Create an Outlook Add-in project with the name OutlookMailItemTaskPane. Use the Outlook Add-in project template. For more information, see How to: Create Office Projects in Visual Studio.

    Visual Studio opens the ThisAddIn.cs or ThisAddIn.vb code file and adds the OutlookMailItemTaskPane project to Solution Explorer.

Designing the User Interface of the Custom Task Pane

There is no visual designer for custom task panes, but you can design a user control with the UI you want. The custom task pane in this add-in has a simple UI that contains a TextBox control. Later in this walkthrough, you will add the user control to the custom task pane.

To design the user interface of the custom task pane

  1. In Solution Explorer, click the OutlookMailItemTaskPane project.

  2. On the Project menu, click Add User Control.

  3. In the Add New Item dialog box, change the name of the user control to TaskPaneControl, and then click Add.

    The user control opens in the designer.

  4. From the Common Controls tab of the Toolbox, drag a TextBox control to the user control.

Designing the User Interface of the Ribbon

One of the goals for this add-in is to give users a way to hide or display the custom task pane from the Ribbon of each e-mail message. To provide the user interface, create a custom Ribbon UI that displays a toggle button that users can click to display or hide the custom task pane.

To create a custom Ribbon UI

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

  2. In the Add New Item dialog box, select Ribbon (Visual Designer).

  3. Change the name of the new Ribbon to ManageTaskPaneRibbon, and click Add.

    The ManageTaskPaneRibbon.cs or ManageTaskPaneRibbon.vb file opens in the Ribbon Designer and displays a default tab and group.

  4. In the Ribbon Designer, click group1.

  5. In the Properties window, set the Label property to Task Pane Manager.

  6. From the Office Ribbon Controls tab of the Toolbox, drag a ToggleButton control onto the Task Pane Manager group.

  7. Click toggleButton1.

  8. In the Properties window, set the Label property to Show Task Pane.

Display the Custom Ribbon User Interface with E-Mail Messages

The custom task pane that you create in this walkthrough is designed to appear only with Inspector windows that contain e-mail messages. Therefore, set the properties to display your custom Ribbon UI only with these windows.

To display the custom Ribbon UI with e-mail messages

  1. In the Ribbon Designer, click the ManageTaskPaneRibbon Ribbon.

  2. In the Properties window, click the drop-down list next to RibbonType, and select Microsoft.Outlook.Mail.Compose and Microsoft.Outlook.Mail.Read.

Creating a Class to Manage Inspector Windows and Custom Task Panes

There are several cases in which the add-in must identify which custom task pane is associated with a specific e-mail message. These cases include the following:

  • When the user closes an e-mail message. In this case, the add-in must remove the corresponding custom task pane to ensure that resources used by the add-in are cleaned up correctly.

  • When the user closes the custom task pane. In this case, the add-in must update the state of the toggle button on the Ribbon of the e-mail message.

  • When the user clicks the toggle button on the Ribbon. In this case, the add-in must hide or display the corresponding task pane.

To enable the add-in to keep track of which custom task pane is associated with each open e-mail message, create a custom class that wraps pairs of Inspector and CustomTaskPane objects. This class creates a new custom task pane object for each e-mail message, and it deletes the custom task pane when the corresponding e-mail message is closed.

To create a class to manage Inspector windows and custom task panes

  1. In Solution Explorer, right-click the ThisAddIn.cs or ThisAddIn.vb file, and then click View Code.

  2. Add the following statements to the top of the file.

    Imports System.Collections.Generic
    Imports Microsoft.Office.Tools
    Imports Office = Microsoft.Office.Core
    Imports Outlook = Microsoft.Office.Interop.Outlook
    
    using Microsoft.Office.Tools;
    
  3. Add the following code to the ThisAddIn.cs or ThisAddIn.vb file, outside the ThisAddIn class (for Visual C#, add this code inside the OutlookMailItemTaskPane namespace). The InspectorWrapper class manages a pair of Inspector and CustomTaskPane objects. You will complete the definition of this class in the following steps.

    Public Class InspectorWrapper
        Private inspector As Outlook.Inspector
        Private WithEvents inspectorEvents As Outlook.InspectorEvents_Event
        Private WithEvents taskPane As CustomTaskPane
    
    public class InspectorWrapper
    {
        private Outlook.Inspector inspector;
        private CustomTaskPane taskPane;
    
  4. Add the following constructor after the code that you added in the previous step. This constructor creates and initializes a new custom task pane that is associated with the Inspector object that is passed in. In C#, the constructor also attaches event handlers to the Close event of the Inspector object and to the VisibleChanged event of the CustomTaskPane object.

    Public Sub New(ByVal Inspector As Outlook.Inspector)
        Me.inspector = Inspector
        inspectorEvents = TryCast(Me.inspector, Outlook.InspectorEvents_Event)
        taskPane = Globals.ThisAddIn.CustomTaskPanes.Add(New TaskPaneControl(), _
            "My task pane", Inspector)
    End Sub
    
    public InspectorWrapper(Outlook.Inspector Inspector)
    {
        inspector = Inspector;
        ((Outlook.InspectorEvents_Event)inspector).Close +=
            new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);
    
        taskPane = Globals.ThisAddIn.CustomTaskPanes.Add(
            new TaskPaneControl(), "My task pane", inspector);
        taskPane.VisibleChanged += new EventHandler(TaskPane_VisibleChanged);
    }
    
  5. Add the following method after the code that you added in the previous step. This method is an event handler for the VisibleChanged event of the CustomTaskPane object that is contained in the InspectorWrapper class. This code updates the state of the toggle button whenever the user opens or closes the custom task pane.

    Private Sub TaskPane_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles taskPane.VisibleChanged
        Globals.Ribbons(inspector).ManageTaskPaneRibbon.ToggleButton1.Checked = taskPane.Visible
    End Sub
    
    void TaskPane_VisibleChanged(object sender, EventArgs e)
    {
        Globals.Ribbons[inspector].ManageTaskPaneRibbon.toggleButton1.Checked = 
            taskPane.Visible;
    }
    
  6. Add the following method after the code that you added in the previous step. This method is an event handler for the Close event of the Inspector object that contains the current e-mail message. The event handler frees resources when the e-mail message is closed. The event handler also removes the current custom task pane from the CustomTaskPanes collection. This helps prevent multiple instances of the custom task pane when the next e-mail message is opened.

    Sub InspectorWrapper_Close() Handles inspectorEvents.Close
        If Not (taskPane Is Nothing) Then
            Globals.ThisAddIn.CustomTaskPanes.Remove(taskPane)
        End If
    
        taskPane = Nothing
        Globals.ThisAddIn.InspectorWrappers.Remove(inspector)
        RemoveHandler inspectorEvents.Close, AddressOf InspectorWrapper_Close
        inspector = Nothing 
    End Sub
    
    void InspectorWrapper_Close()
    {
        if (taskPane != null)
        {
            Globals.ThisAddIn.CustomTaskPanes.Remove(taskPane);
        }
    
        taskPane = null;
        Globals.ThisAddIn.InspectorWrappers.Remove(inspector);
        ((Outlook.InspectorEvents_Event)inspector).Close -=
            new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);
        inspector = null;
    }
    
  7. Add the following code after the code that you added in the previous step. Later in this walkthrough, you will call this property from a method in the custom Ribbon UI to display or hide the custom task pane.

    Public ReadOnly Property CustomTaskPane() As CustomTaskPane
            Get 
                Return taskPane
            End Get 
        End Property 
    End Class
    
    public CustomTaskPane CustomTaskPane
        {
            get
            {
                return taskPane;
            }
        }
    }
    

Initializing and Cleaning Up Resources Used by the Add-In

Add code to the ThisAddIn class to initialize the add-in when it is loaded, and to clean up resources used by the add-in when it is unloaded. You initialize the add-in by setting up an event handler for the NewInspector event and by passing all existing e-mail messages to this event handler. When the add-in is unloaded, detach the event handler and clean up objects used by the add-in.

To initialize and clean up resources used by the add-in

  1. In the ThisAddIn.cs or ThisAddIn.vb file, locate the definition of the ThisAddIn class.

  2. Add the following declarations to the ThisAddIn class:

    • The inspectorWrappersValue field contains all the Inspector and InspectorWrapper objects that are managed by the add-in.

    • The inspectors field maintains a reference to the collection of Inspector windows in the current Outlook instance. This reference prevents the garbage collector from freeing the memory that contains the event handler for the NewInspector event, which you will declare in the next step.

    Private inspectorWrappersValue As New Dictionary(Of Outlook.Inspector, InspectorWrapper)
    Private WithEvents inspectors As Outlook.Inspectors
    
    private Dictionary<Outlook.Inspector, InspectorWrapper> inspectorWrappersValue =
        new Dictionary<Outlook.Inspector, InspectorWrapper>();
    private Outlook.Inspectors inspectors;
    
  3. Replace the ThisAddIn_Startup method with the following code. This code attaches an event handler to the NewInspector event, and it passes every existing Inspector object to the event handler. If the user loads the add-in after Outlook is already running, the add-in uses this information to create custom task panes for all e-mail messages that are already open.

    Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Startup
    
        inspectors = Me.Application.Inspectors
        Dim inspector As Outlook.Inspector
        For Each inspector In inspectors
            Inspectors_NewInspector(inspector)
        Next inspector
    End Sub
    
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        inspectors = this.Application.Inspectors;
        inspectors.NewInspector +=
            new Outlook.InspectorsEvents_NewInspectorEventHandler(
            Inspectors_NewInspector);
    
        foreach (Outlook.Inspector inspector in inspectors)
        {
            Inspectors_NewInspector(inspector);
        }
    }
    
  4. Replace the ThisAddIn_ShutDown method with the following code. This code detaches the NewInspector event handler and cleans up objects used by the add-in.

    Private Sub ThisAddIn_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Shutdown
    
        RemoveHandler inspectors.NewInspector, AddressOf Inspectors_NewInspector
        inspectors = Nothing
        inspectorWrappersValue = Nothing 
    End Sub
    
    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
        inspectors.NewInspector -=
            new Outlook.InspectorsEvents_NewInspectorEventHandler(
            Inspectors_NewInspector);
        inspectors = null;
        inspectorWrappersValue = null;
    }
    
  5. Add the following NewInspector event handler to the ThisAddIn class. If a new Inspector contains an e-mail message, the method creates an instance of a new InspectorWrapper object to manage the relationship between the e-mail message and the corresponding task pane.

    Sub Inspectors_NewInspector(ByVal Inspector As Outlook.Inspector) _
        Handles inspectors.NewInspector
    
        If TypeOf Inspector.CurrentItem Is Outlook.MailItem Then
            inspectorWrappersValue.Add(Inspector, New InspectorWrapper(Inspector))
        End If 
    End Sub
    
    void Inspectors_NewInspector(Outlook.Inspector Inspector)
    {
        if (Inspector.CurrentItem is Outlook.MailItem)
        {
            inspectorWrappersValue.Add(Inspector, new InspectorWrapper(Inspector));
        }
    }
    
  6. Add the following property to the ThisAddIn class. This property exposes the private inspectorWrappersValue field to code outside the ThisAddIn class.

    Public ReadOnly Property InspectorWrappers() As Dictionary(Of Outlook.Inspector, InspectorWrapper)
        Get 
            Return inspectorWrappersValue
        End Get 
    End Property
    
    public Dictionary<Outlook.Inspector, InspectorWrapper> InspectorWrappers
    {
        get
        {
            return inspectorWrappersValue;
        }
    }
    

Checkpoint

Build your project to ensure that it compiles without errors.

To build your project

  • In Solution Explorer, right-click the OutlookMailItemTaskPane project and then click Build. Verify that the project compiles without errors.

Synchronizing the Ribbon Toggle Button with the Custom Task Pane

The toggle button will appear to be pressed in when the task pane is visible, and it will appear to be not pressed in when the task pane is hidden. To synchronize the state of the button with the custom task pane, modify the Click event handler of the toggle button.

To synchronize the custom task pane with the toggle button

  1. In the Ribbon Designer, double-click the Show Task Pane toggle button.

    Visual Studio automatically generates an event handler named toggleButton1_Click, which handles the Click event of the toggle button. Visual Studio also opens the ManageTaskPaneRibbon.cs or ManageTaskPaneRibbon.vb file in the Code Editor.

  2. Add the following statements to the top of the ManageTaskPaneRibbon.cs or ManageTaskPaneRibbon.vb file.

    Imports Microsoft.Office.Tools.Ribbon
    Imports Outlook = Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Tools
    
    using Outlook = Microsoft.Office.Interop.Outlook;
    using Microsoft.Office.Tools;
    
  3. Replace the toggleButton1_Click event handler with the following code. When the user clicks the toggle button, this method hides or displays the custom task pane that is associated with the current Inspector window.

    Private Sub ToggleButton1_Click(ByVal sender As System.Object, _
        ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _
        Handles ToggleButton1.Click
    
        Dim inspector As Outlook.Inspector = e.Control.Context
        Dim inspectorWrapper As InspectorWrapper = Globals.ThisAddIn.InspectorWrappers(inspector)
        Dim taskPane As CustomTaskPane = inspectorWrapper.CustomTaskPane
        If Not (taskPane Is Nothing) Then
            taskPane.Visible = TryCast(sender, RibbonToggleButton).Checked
        End If 
    End Sub
    
    private void toggleButton1_Click(object sender, RibbonControlEventArgs e)
    {
        Outlook.Inspector inspector = (Outlook.Inspector)e.Control.Context;
        InspectorWrapper inspectorWrapper = Globals.ThisAddIn.InspectorWrappers[inspector];
        CustomTaskPane taskPane = inspectorWrapper.CustomTaskPane;
        if (taskPane != null)
        {
            taskPane.Visible = ((RibbonToggleButton)sender).Checked;
        }
    }
    

Testing the Project

When you start debugging the project, Outlook opens and the add-in is loaded. The add-in displays a unique instance of the custom task pane with each e-mail message that is opened. Create several new e-mail messages to test the code.

To test the add-in

  1. Press F5.

  2. In Outlook, click New to create a new e-mail message.

  3. On the Ribbon of the e-mail message, click the Add-Ins tab, and then click the Show Task Pane button.

    Verify that a task pane with the title My task pane is displayed with the e-mail message.

  4. In the task pane, type First task pane in the text box.

  5. Close the task pane.

    Verify that the state of the Show Task Pane button changes so that it is no longer pressed.

  6. Click the Show Task Pane button again.

    Verify that the task pane opens, and that the text box still contains the string First task pane.

  7. In Outlook, click New to create a second e-mail message.

  8. On the Ribbon of the e-mail message, click the Add-Ins tab, and then click the Show Task Pane button.

    Verify that a task pane with the title My task pane is displayed with the e-mail message, and the text box in this task pane is empty.

  9. In the task pane, type Second task pane in the text box.

  10. Change focus to the first e-mail message.

    Verify that the task pane that is associated with this e-mail message still displays First task pane in the text box.

This add-in also handles more advanced scenarios that you can try. For example, you can test the behavior when viewing e-mails by using the Next Item and Previous Item buttons. You can also test the behavior when you unload the add-in, open several e-mail messages, and then reload the add-in.

Next Steps

You can learn more about how to create custom task panes from these topics:

See Also

Tasks

How to: Add a Custom Task Pane to an Application

Walkthrough: Automating an Application from a Custom Task Pane

Walkthrough: Synchronizing a Custom Task Pane with a Ribbon Button

Concepts

Accessing the Ribbon at Run Time

Other Resources

Custom Task Panes

Ribbon Overview

Outlook Object Model Overview