CAB: Use the Outlook Bar in your CAB applications

UPDATE: I moved the code to codeplex.


A frecuently requested feature in the CAB community is a navigation control like Microsoft Outlook’s bar. Chris Holmes posted a few days ago a nice approach on how to achieve this using CAB:


In CAB Reference Implementation 2 (Global Bank Branch WorkBench), an IconTabWorkspace is introduced. The functionallity of the workspace is similar to Outlook’s bar, but it just displays icons (ToolStripButtons):

At Southworks, we liked both ideas and put them together to create an OutlookBarWorkSpace:

OutlookBar workspace showing the Mails smartpartCalendar module was selected and the smartpart has been shown
Use of the splitterShow more/fewer buttons

You can download it from here.


Use it as every CAB Workspace! Add SmartParts using:

  • void Show(object smartPart) and having your SmartPart implement ISmartInfoProvider or 
  • void Show(object smartPart, ISmartPartInfo smartPartInfo)

But take into account that in both cases you have to provide an OutlookBarSmartPartInfo, which will contain needed information to create the buttons.
OutlookBarSmartPartInfo has the following members in addition to those included in the SmartPartInfo base class:

  • Icon: bitmap to be displayed in the button.
  • (Optional) ImageTransparentColor: transparent color on the item’s icon for images that support transparency
  • (Optional) EventTopicName: EventTopic that will be raised when clicking the button. This is useful, for example, when you need to update another workspace (much like what MS Outlook does).

Apart from these members, the OutlookBarWorkspace uses the Title property to set the button’s text.

This code is provided "AS IS" with no warranties, and confers no rights.

– The implementation of the stack strip is based on a sample written by Joe Stegman
Mariano Szklanny helped writing the workspace implementation
– The office icons might be used only if you have a valid Microsoft Office license


  • Chris Holmes says:

    Awesome work Matias! I am so happy to see you take this and run with it!

    This is exactly what I hoped for when I posted my code. Nice work!

  • http:// says:

    Excellent work. This is just fantastic! Thank you so much.

  • http:// says:

    You and I had exactly the same idea! The sample with HeaderStrip, StackStrip, etc. + CAB + Chris Holmes’ initial start = awesome.

    Though, I’ve approached it differently, making an OutlookBar that is both a Workspace and a UIExtensionSite. I hope to get a blog up and going to share the code soon.

    Great stuff. Thanks for this code, Matias.

  • http:// says:

    Excellent work.

    Found a bug on line 202:
    string eventTopic = _topics[button.Text];

    Crashes if _topics doesn’t contain given key.
    Changed this line to:
    if( _topics.ContainsKey( button.Text ) )
    and all is good.

    Cheers, Greg.

  • matiaswoloski says:

    Hi Greg,

    good catch.
    Indeed, for better perf, it should be implemented like this


  • http:// says:

    It will be cool if this workspace is dockable/pinnable.

  • http:// says:

    Can you provide an example on how to use EventTopicName?

  • Matias Woloski says:

    The Event Publication feature of the OutlookBar workspace is used like this:

    OutlookSmartPartInfo ospi = new OutlookSmartPartInfo();
    ospi.EventTopicName = “OnMailPressed”;
    ospi.Title = “Mail”;
    ospi.Icon = Resources.MailIcon;
    ws.Show( myView, ospi );

    The workspace will associate the event topic with the click of the Mail button. So in your Mail ModuleController you could have

    public void OnMailPressed(object sender, EventArgs e) {
    // do something because the Mail button was pressed


  • http:// says:

    I want to change theme to classic (gray) in windows XP…is it possible? If yes then how? Can someone share their code?

  • http:// says:

    How to have the Mail Button(pressed in orange) be default button on the load like outlook?

  • http:// says:


    This is how I resolved the issue:

    Override the OnLoad Event Handler in the class, OutlookBarWorkspace, and add the following code after the call to base.OnLoad(e);

    // Cast ActiveSmartPart to SmartPartInfoProvider
    ISmartPartInfoProvider activeSmartPartProvider = this.ActiveSmartPart as ISmartPartInfoProvider;

    // Obtain SmartPart details from the SmartPartInfo object
    ISmartPartInfo activeSmartPartInfo = activeSmartPartProvider.GetSmartPartInfo(typeof(OutlookBarSmartPartInfo));

    // Cycle through the SmartPart collection and activate the ToolStripButton with the matching title.
    foreach (ToolStripButton toolStripButton in _smartParts.Values)
    toolStripButton.Checked = activeSmartPartInfo.Title == toolStripButton.Text;

    Anyone disagree with this approach?


  • http:// says:

    I realy need an working example of the great looking OutlookBarWorkspace. I have no idea where to start adding buttons and smartparts. In the Shell? I managed to add just one button in the WorkItem.Run() method, but i assume it is not the right place.
    Thanks for help

  • http:// says:

    Great work! I’m just starting with CAB and this really helped.

    One question: How can I set a particular button/smartpart to be activated at load? I get the header for the last one added but the smartpart isn’t displayed.

  • MikeWo says:

    Meenu, HCGL, David:

    I was also trying to be able to set the header to specific smartpart. It seemed like the Activate function should do the trick, but while it did make the related smartpart the active smart part, it didn’t update the header. It called the OnSmartpartActivitated method in OutlookBarWorkspace but that did a cast on the smart part to ISmartPartInfo to get the text to set the header, which was never the case for me since I was passing a reference to the smartPart itself, not the smartPartInfo. I added a line to the Active method, it now looks like this:

    public void Activate(object smartPart)
    ToolStripButton relatedButton;
    if (_smartParts.TryGetValue(smartPart, relatedButton))
    _headerLabel.Text = relatedButton.Text.Trim();
    } }

    No need to loop through the smart parts collections to find it. I feel like I’m missing something as to why the Activate seems to have expected a SmartPartInfo though.

  • MikeWo says:

    Whoops, forgot the out in the TryGetValue method. That line should look like this:

    if (_smartParts.TryGetValue(smartPart, out relatedButton))

  • http:// says:


    I am trying to create a Outlook workspace from scratch using WPF. Can you guide me how to start with this. Right now I have created OutlookWS.cs and also implementing the OutlookWSSmartPartInfo.cs.

    What are you using for buttons? Are you using tab workspace/ deck workspace inside ur workspace.

    Please let me know, this is urgent.

    Thanks for ur time.

  • ChrisA says:

    How do I implement this with Outlook 2002?
    (vrsn. 10.3513…) on Windows XP

Leave a Reply