Pieter van der Westhuizen

Outlook views: How to create a custom view for calendar, task, mail items

This is the second article of the Outlook 2013 add-in development in VS 2012 for beginners series that examines Outlook views and covers the following aspects:

What are Outlook views?

Outlook views allow you to group, sort and view all the different types of Outlook data within the View panel of the Outlook Explorer window. Outlook comes with a few built-in views for each Outlook item type (mail, task, calendar, etc.) which can be accessed via the View tab.

Build-in Outlook views are accessible via the View tab

Outlook supports six View objects. These objects inherit from the Outlook View object and represent different ways of displaying data in Outlook. These objects are:

  • TableView – Allows you to view data in a simple table/grid layout.
  • IconView – Shows data as icons in a similar fashion as the Windows Explorer icon view.
  • BusinessCardView – This view is synonymous with the Outlook Contacts folder. It allows you to view data as a collection of business cards.
  • CalendarView – This is the default view used by the Outlook Calendar, but you can also use it to view other data.
  • CardView – Allows you to view data as a series of cards.
  • TimelineView – Shows data in a linear time line, similar to the Outlook Journal folder.

How to enumerate and access views for a folder

In order to enumerate through the views collection of a particular Outlook folder, you can use the following code:

C# code example

Outlook._Explorer currExplorer = null;
Outlook.MAPIFolder currFolder = null;
Outlook.Views views = null;
Outlook.View view = null;
 
try
{
    currExplorer = OutlookApp.ActiveExplorer();
    currFolder = currExplorer.CurrentFolder;
    views = currFolder.Views;
 
    for (int i = 1; i <= views.Count; i++)
    {
        view = views[i];
        Console.WriteLine(view.Name);
        Marshal.ReleaseComObject(view);
    }                
}
finally
{
    if (views != null)
        Marshal.ReleaseComObject(views);
    if (currFolder != null)
        Marshal.ReleaseComObject(currFolder);
    if (currExplorer != null)
        Marshal.ReleaseComObject(currExplorer);
}

The View object exposes methods and properties common to all views. If you need to access properties specific to a certain type of view for example the AllowInCellEditing property of the TableView object, you need to cast the View object to a TableView object. To save any properties that changed, you need to call the Apply method as illustrated below:

C# code example

Outlook._Explorer currExplorer = null;
Outlook.MAPIFolder currFolder = null;
Outlook.View view = null;
Outlook.TableView tableView = null;
 
try
{
    currExplorer = OutlookApp.ActiveExplorer();
    currFolder = currExplorer.CurrentFolder;
    view = currFolder.CurrentView;
 
    if (view.ViewType == Outlook.OlViewType.olTableView)
    {
        tableView = view as Outlook.TableView;
	 tableView.AllowInCellEditing = true;
        tableView.Apply();
    }
}
finally
{
    if (view != null)
        Marshal.ReleaseComObject(view);
    if (currFolder != null)
        Marshal.ReleaseComObject(currFolder);
    if (currExplorer != null)
        Marshal.ReleaseComObject(currExplorer);
}

Built-in vs. custom Outlook views

Whilst enumerating through all the views in a folder, you might need to determine which views are custom user created views and which are standard built-in views. The View object exposes the Standard property which you can use to easily distinguish between a custom and a standard Outlook view, for example:

C# code example

Outlook._Explorer currExplorer = null;
Outlook.MAPIFolder currFolder = null;
Outlook.Views views = null;
Outlook.View view = null;
 
try
{
    currExplorer = OutlookApp.ActiveExplorer();
    currFolder = currExplorer.CurrentFolder;
    views = currFolder.Views;
 
    for (int i = 1; i <= views.Count; i++)
    {
        view = views[i];
        if (view.Standard)
        {
            Console.WriteLine(view.Name + " is a built-in view");
        }
        else
        {
            Console.WriteLine(view.Name + " is a custom view");
        }
        Marshal.ReleaseComObject(view);
    }
}
finally
{
    if (views != null)
        Marshal.ReleaseComObject(views);
    if (currFolder != null)
        Marshal.ReleaseComObject(currFolder);
    if (currExplorer != null)
        Marshal.ReleaseComObject(currExplorer);
}

How to create a custom Outlook view

You can create your own custom view using the Outlook object model. In the following code listing, I’ve added a user property to a calendar folder, created a new TableView for the folder and added the custom property to the view.

C# code example

Outlook.Explorer currExplorer = null;
Outlook.MAPIFolder currFolder = null;
Outlook.Views views = null;
Outlook.TableView tableView = null;
Outlook.ViewFields viewFields = null;
Outlook.ViewField viewField = null;
Outlook.ColumnFormat columnFormat = null;
 
Outlook.UserDefinedProperties userProperties = null;
Outlook.UserDefinedProperty billableProperty = null;
 
try
{
    currExplorer = OutlookApp.ActiveExplorer();
    currFolder = currExplorer.CurrentFolder;
 
    // Create User Property
    userProperties = currFolder.UserDefinedProperties;
    billableProperty = userProperties.Add("Billable", Outlook.OlUserPropertyType.olYesNo);
 
    views = currFolder.Views;
    views.Remove("My Custom View");
 
    tableView = (Outlook.TableView)views.Add("My Custom View",
        Outlook.OlViewType.olTableView,
        Outlook.OlViewSaveOption.olViewSaveOptionThisFolderEveryone);
    viewFields = tableView.ViewFields;
    viewField = viewFields.Add("Billable");
    columnFormat = viewField.ColumnFormat;
    columnFormat.Align = Outlook.OlAlign.olAlignCenter;
 
    tableView.Save();
    tableView.Apply();
}
finally
{
    if (userProperties != null)
        Marshal.ReleaseComObject(userProperties);
    if (billableProperty != null)
        Marshal.ReleaseComObject(billableProperty);
    if (viewFields != null)
        Marshal.ReleaseComObject(viewFields);
    if (viewField != null)
        Marshal.ReleaseComObject(viewField);
    if (columnFormat != null)
        Marshal.ReleaseComObject(columnFormat);
    if (tableView != null)
        Marshal.ReleaseComObject(tableView);
    if (views != null)
        Marshal.ReleaseComObject(views);
    if (currFolder != null)
        Marshal.ReleaseComObject(currFolder);
    if (currExplorer != null)
        Marshal.ReleaseComObject(currExplorer);
}

How to remove a custom Outlook view

To remove a custom view, you need to use the Remove method on the views collection. Be careful though, if you try to remove one of the built-in Outlook views an error will be thrown. To delete the custom view we’ve created previously, use the following code:

C# code example

Outlook.Explorer currExplorer = null;
Outlook.MAPIFolder currFolder = null;
Outlook.Views views = null;
 
try
{
    currExplorer = OutlookApp.ActiveExplorer();
    currFolder = currExplorer.CurrentFolder;
    views = currFolder.Views;
    views.Remove("My Custom View");              
}
finally
{
    if (views != null)
        Marshal.ReleaseComObject(views);
    if (currFolder != null)
        Marshal.ReleaseComObject(currFolder);
    if (currExplorer != null)
        Marshal.ReleaseComObject(currExplorer);
}

Useful events

ViewAdd and ViewRemove events

The Views object exposes two events for handling the removal and addition of views. To declare view handlers for the events use the following code:

views.ViewAdd += views_ViewAdd;
views.ViewRemove += views_ViewRemove;

Both of the events have a parameter that contains a reference to the View being added or removed. The code for the event handlers could be similar to the following:

void views_ViewRemove(Outlook.View View)
{
    Console.WriteLine(View.Name);
}
 
void views_ViewAdd(Outlook.View View)
{
    Console.WriteLine(View.Name);
}

BeforeViewSwitch and ViewSwitch events

These two events are similar in the fact that both are triggered when a view changes in the Outlook Explorer. However, as the BeforeViewSwitch event’s name suggests this event occur before the view is changed.

To access these two events, you first need to add an Outlook Events component to the AddinModule designer surface. In this components’ list of events generate an event handler for the event by double-clicking next to its name in the properties window.

private void adxOutlookEvents_ExplorerBeforeViewSwitch(object sender,
    ADXOlExplorerBeforeViewSwitchEventArgs e)
{
    string newView = e.NewView.ToString();
 
    if (!newView.Equals("My Custom View"))
    {
	e.Cancel = true;
    }
}

In the above code, I get a reference to the new view the Outlook Explorer is switching to and if it is a standard view, I cancel the event. Thus preventing the user from switching to any standard built-in Outlook view from a custom view.

The ExplorerViewSwitch event occurs after the user changed the view and has a parameter which contains a reference to the Outlook Explorer in which the event occurred. In the following code I use the explorer parameter to get a reference to the active Outlook Explorer and the currently active view.

private void adxOutlookEvents_ExplorerViewSwitch(object sender, object explorer)
{
    Outlook.Explorer currExplorer = null;
    Outlook.View currView = null;
 
    try
    {
        currExplorer = explorer as Outlook.Explorer;
        currView = currExplorer.CurrentView as Outlook.View;
        Console.WriteLine(currView.Name);                
    }
    finally
    {
        if (currView != null)
            Marshal.ReleaseComObject(currView);
    }
}

Thank you for reading. Until next time, keep coding!

Available downloads:

This sample was created using Add-in Express for Office and .net:

C# Outlook add-in

Outlook 2013 add-in development in Visual Studio 2012 for beginners

You may also be interested in:

16 Comments

  • Fabrice says:

    Nice article
    But do you have any tip on how to display an icon in a Table View column ? like the “Icon” built-in column ?
    i.e. I’ve my custom property, I add a column in the view and set the view, but I only succeed to display text without any formatting.
    Thank you

  • Pieter van der Westhuizen says:

    Hi Fabrice,

    As far as I know it’s not possible to include your own icon on a view column. I did find something that sounds like it might work : https://www.outlookcode.com/threads.aspx?forumid=3&messageid=31897

    Thanks for your comment!

  • Fabrice says:

    The link you gave show away to change the built-in icon for an item (by changing the MessageClass) but it doesn’t show a way to display an icon for a custom property.
    I think it’s simply not possible in outlook.

    Thank you for your search

  • Senthil says:

    HI,
    Hope you are doing great.
    is it possible to Bring Private key message button in new composing email.

    THanks
    Senthil

  • Pieter van der Westhuizen says:

    Hi Senthil,

    Could you please provide more detail of what you want to accomplish? What do you mean with a private key message?

  • Mesfin85 says:

    Pieter,
    In the above ExplorerBeforeViewSwitch event procedure, newView gets a null value during the assignment under: Outlook.View newView = e.NewView as Outlook.View;
    When testing this, I am not able to check if newView.Standard is true or not as the value is always null and causes null reference exception when running the if condition ( if (newView.Standard))
    Any idea on how to assign it other than the example shows?
    I did test the example project on my system with VS2010 pro and Add-in Express .net premium in win7 (32) and office 2013.
    Thanks

  • Pieter van der Westhuizen says:

    Hi There,

    Apologies. I made a mistake in the sample code. e.NewView contains the name of the view, so you would have to check for a string value e.g:

    string newView = e.NewView.ToString();
    if (!newView.Equals(“My Custom View”))
    {
    e.Cancel = true;
    }

    The code in the post has been updated to reflect this.

  • Mesfin85 says:

    Pieter,
    Thanks so much for the changes. I was struggling with why the object was not being able to be reassigned after casting. Accessing it by the string value will work as well.
    Regards

  • Mesfin85 says:

    Dear Pieter,

    I am interested in building on the above idea and making property “Billable” visible and update-able in both the main outlook folder and mail item level when the item is opened (or at least update-able in the main folder but visible in both).
    In a different blog, titled “Working with custom Outlook properties: C# code examples “ (https://www.add-in-express.com/creating-addins-blog/custom-outlook-properties/), you explain how you can use the parameter AddToFolderFields (of the Add method) of Outlook.UserProperties to show custom fields at item and folder level.
    I am wondering if it is possible (and if so, how) to create user properties at item level and displaying them in a different way than using custom form as in your other example (for example by displaying them in a similar way categories are shown when a mail item (with one or more assigned categories) is opened?

    Thanks so much for the help.
    -MG

  • Mesfin85 says:

    Pieter, Add-in Express Team,

    Please find below details for additional info.
    Scenario (Works)
    1) Create a (table) view with a custom field and property tag:
    “https://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/ColorID”
    2) Apply the view in the main explorer (Inbox)
    3) Select a mail item and add a user property “ColorId”. Set the third parameter of the add method of Outlook.UserProperties (AddToFolderFields) to true.
    4) Assign the property a value using the property’s string value
    5) The value is reflected in the display of the main explorer window
    6) Reading the value using the PropertyAccessor shows the assigned value at the item level.
    In trying the above scenario with a custom field, for example “Billable” the process doesn’t work as the property tag schema cannot be used to add a field to the view (I can only create the field (in the view) by the string value of the custom field)
    The questions I have are
    1) If I have missed anything to replicate scenario 1 with custom user properties (fields) not included in the strings namespace
    2) If you know of any place to find documentation or list of property tags for the properties under the string namespace
    3) If there is a way to change the display name of the property tag (eg. “ColorId” to something else) in the custom view.
    Thank you
    -MG

  • Pieter van der Westhuizen says:

    Hi,

    I’m not sure I follow. If you follow the example, you’ll see we’re adding user properties using the UserDefinedProperties object and then adding them to the view using the viewFields object.

    Is this not working for you?

  • Mesfin85 says:

    Pieter,

    Understand. Thanks.
    The part to add user properties works fine. I was trying to accomplish something else, which on a second thought is beyond the scope of this article, so please consider this as closed.
    I will check it further and if necessary create a separate request/thread.

    Regards,
    -MG

  • Fabrice says:

    Is it possible to set the Compact mode via code ?
    In Outlook it’s possible via View Settings > Other Settings > Use compact layout

    Thank you

  • Pieter van der Westhuizen says:

    Hi Fabrice,

    I could’nt find a way to do it in code. You could perhaps try setting the views’ XML property to the same XML of a view that has this property set and see if that will work?
    Let us know.

  • Fabrice says:

    I also think there is a small error which could produce an undisposed com reference:

    viewField = tableView.ViewFields.Add(“Billable”);

    should be:

    viewField = viewFields.Add(“Billable”);

  • Pieter van der Westhuizen says:

    Hi Fabrice,
    Thanks for letting us know.
    It has been corrected.

Post a comment

Have any questions? Ask us right now!