If you decide to build an Outlook add-in, you’re going to want to customize the user interface.
If you start customizing the Outlook user interface, you’ll probably build a custom ribbon.
If you build a custom Outlook ribbon, you’ll want to put some controls on it like a button that toggles, a checkbox, and a drop down control.
If you add these types of controls and finish writing your code, you’ll want to test your add-in.
If you hit F5, start Outlook, and test your addin, you’ll be tempted to open multiple inspector windows.
If you open multiple inspector windows, click your controls, and switch back and forth between inspectors…
You will discover the problem I am to solve today.
- Multiple Outlook inspectors, multiple problems
- A strategy for maintaining a separate ribbon control state
- Building the Outlook add-in project
Multiple Outlook inspectors, multiple problems?
Outlook utilizes two types of windows. The primary window is the Outlook Explorer window in which the user navigates between the main parts of Outlook (e.g. mail, contacts, calendar, etc.). Typically, you only have one Outlook explorer window open, although you can open multiple.
The secondary window is the Outlook Inspector window. This is the window that displays individual Outlook items (e.g. mail, contacts, calendar, etc.). It is quite common to have multiple inspector windows open at any given time. And this is the source of our problem.
What we want… what we expect… is for our custom ribbon to behave like Figure 1. But…
Custom Ribbons do not preserve their state across multiple inspector windows by default. You have to code this functionality.
Figure 1. Two Outlook inspector windows maintaining separate control states

This is our problem. How do we make it happen? I’m so glad you asked!
A strategy for maintaining a separate ribbon control state
Boiled down to its essence, the strategy is to create a custom user property and store its value in the Outlook item displayed in the inspector window. If you have multiple controls you want to maintain, you add additional user properties (see Figure 2).
Figure 2. How to maintain a control’s state across all open Outlook inspector windows

When the user takes an action that changes the control’s state, you update the control’s corresponding user property. When the user switches between Outlook inspector windows, you set the control state by reading the corresponding user properties and updating the ribbon controls.
Building the Outlook add-in project
This plugin for Outlook 2013, 2010 and 2007 includes a single custom ribbon with three controls: a button, a checkbox, and a drop down. In terms of code, there are a handful of methods (custom methods and control events). We are going to use Add-in Express for Office and .net.
With Visual Studio open (I’m using Visual Studio 2012), create a new project according to these steps.
- Create a new ADX COM Add-in project. Move through the New Microsoft Office COM Add-in wizard dialog and select VB.NET as in this example, or C#, or C++, as the language of choice and Microsoft Office as the target application. The minimum supported version needs to be Office 2007 or higher.
- After you have the project open in Visual Studio, add an ADXRibbonTab control to the AddinModule‘s in design surface. Change its Caption property to Preserve State.
- Add a ribbon button group (AdxRibbonButtonGroup control) to ribbon tab and set its caption to Preservation Group.
- Add a button (AdxRibbonButtoncontrol) to the ribbon button group and set these properties:
- Caption = FlagIt!
- Size = Large
- ToggleButton = True
- ImageMSO = FlagToday
- Add a check box (AdxRibbonCheckBox control) to the button group and set its caption to Check Me Out.
- Add a drop-down control (AdxRibbonDropdown)to the group.
- Its caption needs to be Favorite Major.
- Add five items to the items collection and set their captions to: (None), Australian Open, French Open, Wimbledon, and U.S. Open respectively.
- Set the drop-down’s SelectedItemIndex property to 0.
Hopefully, your Outlook ribbon is similar to Figure 3.
Figure 3. The custom ribbon in design view

Writing the code
Before we write some code, you need to add Outlook events to the AddinModule. Right click on the AddInModule design surface and click Add Events. In the Add Application Events dialog box select Microsoft Outlook Events and click OK. This action adds an adxOutlookEvents control to the AddInModule and make Outlook events available in the AddinModule class.
Now we are ready to code.
The InspectorActivate Event
We’ll begin with the end. The InspectorActivate event is the one that syncs control state with the Outlook item’s custom user properties. Open the AddInModule’s code view and add the following code:
Private Sub adxOutlookEvents_InspectorActivate(sender As Object, _
inspector As Object, folderName As String) _
Handles adxOutlookEvents.InspectorActivate
Dim flagValue As String = GetStateProperty(inspector, "FlagIt")
AdxRibbonButton1.Pressed = False ' default value
If Not String.IsNullOrEmpty(flagValue) Then
AdxRibbonButton1.Pressed = Convert.ToBoolean(flagValue)
End If
Dim checkValue As String = GetStateProperty(inspector, "CheckIt")
AdxRibbonCheckBox1.Pressed = False ' default value
If Not String.IsNullOrEmpty(checkValue) Then
AdxRibbonCheckBox1.Pressed = Convert.ToBoolean(checkValue)
End If
Dim favValue As String = GetStateProperty(inspector, "Favorite")
AdxRibbonDropDown1.SelectedItemIndex = 0 ' default index
If Not String.IsNullOrEmpty(favValue) Then
AdxRibbonDropDown1.SelectedItemIndex = Convert.ToInt32(favValue)
End If
End Sub
This procedure does the same thing three times… once for each of our Outlook ribbon controls as follows:
- Calls the GetStateProperty function (explained further below) and stores it in a variable.
- Sets the default state of the control.
- If a value was returned by GetStateProperty, it sets the value of the control’s relevant state property (i.e. Pressed or SelectedItemIndex).
This is how the magic happens but there is a supporting cast of methods.
SetStateProperty method – save the control’s state to the user property
The SetStateProperty method accepts two parameters: propName and propValue. The method then retrieves the user property and sets its value. If the user property does not exist, the method creates it. Insert the following code into the AddinModule class.
Private Sub SetStateProperty(propName As String, propValue As String)
Dim inspector As Outlook._Inspector = Me.OutlookApp.ActiveInspector
Dim mailItem As Outlook._MailItem = Nothing
Dim userProperties As Outlook.UserProperties = Nothing
Dim userProperty As Outlook.UserProperty = Nothing
mailItem = TryCast(inspector.CurrentItem, Outlook._MailItem)
If mailItem IsNot Nothing Then
userProperties = mailItem.UserProperties
userProperty = userProperties.Find(propName)
If (userProperty IsNot Nothing) Then
userProperty.Value = propValue
Else
userProperty = userProperties.Add(propName, Outlook.OlUserPropertyType.olText)
userProperty.Value = propValue
End If
mailItem.Save()
End If
If userProperty IsNot Nothing Then Marshal.ReleaseComObject(userProperty)
If userProperties IsNot Nothing Then Marshal.ReleaseComObject(userProperties)
If mailItem IsNot Nothing Then Marshal.ReleaseComObject(mailItem)
If inspector IsNot Nothing Then Marshal.ReleaseComObject(inspector)
End Sub
The method also checks to ensure it is working with the mail item and cleans up its reference COM objects.
GetStateProperty function – retrieve the user property’s value
GetStateProperty works like SetStateProperty but in reverse. This function accepts a context object and a propName string as parameters. The context is the inspector window while the propName is the user property whose values we want to retrieve. Insert the following code into the AddinModule class.
Private Function GetStateProperty(context As Object, propName As String) As String
Dim result As String = String.Empty
Dim inspector As Outlook._Inspector = TryCast(context, Outlook._Inspector)
If inspector IsNot Nothing Then
Dim mailItem As Outlook._MailItem = TryCast(inspector.CurrentItem, Outlook._MailItem)
If mailItem IsNot Nothing Then
Dim userProperties As Outlook.UserProperties = mailItem.UserProperties
Dim userProperty As Outlook.UserProperty
userProperties = mailItem.UserProperties
userProperty = userProperties.Find(propName)
If userProperty IsNot Nothing Then
result = userProperty.Value.ToString()
Marshal.ReleaseComObject(userProperty)
End If
Marshal.ReleaseComObject(userProperties)
Marshal.ReleaseComObject(mailItem)
End If
End If
Return result
End Function
AdxRibbonButton1_OnClick Event
The ribbon button’s click event calls the SetStateProperty method. It specifies “FlagIt” as the propName and passes the button’s pressed state as a string value.
Private Sub AdxRibbonButton1_OnClick(sender As Object, _
control As IRibbonControl, pressed As Boolean) _
Handles AdxRibbonButton1.OnClick
SetStateProperty("FlagIt", pressed.ToString())
End Sub
AdxRibbonCheckBox1_OnClick Event
The ribbon check box’s click event calls the SetStateProperty method. It specifies “CheckIt” as the propName and passes the check box’s pressed state as a string value.
Private Sub AdxRibbonCheckBox1_OnClick(sender As Object, _
control As IRibbonControl, pressed As Boolean) _
Handles AdxRibbonCheckBox1.OnClick
SetStateProperty("CheckIt", pressed.ToString())
End Sub
AdxRibbonDropDown1_OnAction Event
The ribbon drop down’s OnAction event also calls the SetStateProperty method. It specifies “Favorite” as the propName and passes the drop down control’s selectedIndex value as a string.
Private Sub AdxRibbonDropDown1_OnAction(sender As Object, _
control As IRibbonControl, selectedId As String, selectedIndex As Integer) _
Handles AdxRibbonDropDown1.OnAction
SetStateProperty("Favorite", selectedIndex.ToString())
End Sub
Give it a test
You are now ready to test the add-in. If you have Outlook open, close it. Then press F5 in Visual Studio. When Outlook displays, open a few mail items in inspector windows. Change some custom ribbon controls’ state values and switch between inspectors. Your controls should successfully maintain their property state:

If they don’t, you can complain to the author in the comments section.
If you complain to the author, he’ll probably become bothered.
If he becomes bothered, he’ll spend all day wondering why it didn’t work.
If he spends all day wondering why it didn’t work, he’ll find a fix.
If he finds a fix, he’ll post it in the comments…
Available downloads:
This sample Outlook add-in was developed using Add-in Express for Office and .net:
Sample Outlook PreserveState add-in – VB.NET

2 Comments
Awesome, makes much more sense than my unfinished article from a few years ago! How did you do this without using Invalidate and Property Changing?? Mind = blown!
Thanks Eric. I started down the path of using Property Changing but it wasn’t 100% reliable. With some help from Dmitry, I moved to using the click (or onChange events).
Rock On my friend!