September 2008 - Posts
A little while ago, I sat down with Larry Clarkin to record an episode of the Thirsty Developer about the Office Communicator Vista Gadget project that we recently published on CodePlex.
I just finished listening to the podcast - it never gets any less weird hearing your own voice - and it turned out great.
Check out the show, and be sure to download the gadget from CodePlex and give it a try.
Please visit http://www.MOSSCamp.net for more information.
Follow us on twitter at @MOSSCamp.
Hope to see you there!
Save the date! MOSSCamp 2008 is happening on Friday, November 14th.
Matt Morse from PointBridge and I will be organizing this year's event, which Clarity Consulting will be hosting.
We're going with a different format this year. We'll be building a end-to-end application throughout the day, and then putting it together to publish on CodePlex. The idea is to showcase some development best practices for building SharePoint applications. If like me, you've seen your share of horribly developed SharePoint applications, you should enjoy this.
The popular Airing of Grievances will also be back :)
We'll have an event registration page ready by the end of this week. Be sure to register early, last year's event was standing room only!
Keep an eye on this and Matt's blog for more information.
For more information, check out the MOSSCamp web site at http://www.mosscamp.net
Follow MOSSCamp updates on twitter: @MOSSCamp
The WPF Presence Controls for Office Communicator are a set of controls that allow developers to show presence and availability of contacts in their WPF applications.
If you haven't had a chance to use these controls, please see my previous post about them, or download and install them from MSDN.
In this post, I'll go over how to extend the Persona (also applies to PersonaList) control's context menu to include custom menu items specific to your application.
CustomMenuItemClickedEventArgs
This is a simple container class that allows you to differentiate between different custom menu actions being clicked. The class exposes SipUri as a property because custom menu items can also be used in the PersonaList control.
Defining a Custom Menu Item
The first step is to create a List<System.Windows.Controls.MenuItem> to contain all the custom menu items that you would like to define.
The next step is to create a MenuItem object and set its Header and Name properties.
You can then add the new item to the List<MenuItem> object, and finally set the Personal control's CustomMenuItemList property to that list.
Wiring Up the MenuItem Clicked Event
We can use a single event handler to handle the click events of all the custom context menu items defined in the application.
The properties of CustomMenuItemClickedEventArgs allow us to determine which custom menu item was clicked, and from which instance of the Persona control.
Seeing it in Action

Because we're using the MenuItem object, we're relying on its Name and Header properties to figure out which item was clicked.
It's best to come up with an elegant way to store the names of your custom menu items so you're not passing and comparing string variables.
We recently built a set of WPF presence controls to use with Office Communicator 2007 applications.
The WPF presence controls are now available for download on MSDN.
We've used these controls in several WPF applications, including the Microsoft Office Communicator Vista Gadget project that we just published on CodePlex.
The MSDN download includes the complete source code of the presence controls, along with a sample application that shows the various ways of using them.
Note: The MSI installs the source code into a directory under C:\Program Files\ by default. Visual Studio doesn't seem to play nice with solutions that live there. Before attempting to compile the solution, I recommend moving the files to another location, and changing them so that they're not read-only.
Configurability / Extensibility
An important goal when building these controls was to expose their properties to the developer as configurable options. We wanted to ensure that the developer could tailor the use of the controls specifically to their application. All of these properties are exposed as WPF Dependency Properties.
Additionally, the controls are built in such a way so that a developer can use them as building blocks for other controls. We followed that mantra ourselves when building the controls, e.g. the PersonaList and MyPersona controls are built on top of the Persona control.
Presence Controls
The project includes three controls:
- Persona
- PersonaList
- MyPersona
Persona
The Persona control is used to display the presence and availability of a single user.
The Persona control exposes the following properties:
- SipUri
- The Sip URI of the contact to bind the Persona control to
- ShowContextMenu
- Show the Persona control's context menu via right-click
- The context menu provides options for communicating with the contact
- ShowDisplayName
- Show the display name of the contact with the given Sip URI
- ShowAvailability
- Show the availability (availability != presence) of the contact
- ShowToolTip
- Show a summary tooltip when hovering over the control
- ShowDetailedToolTip
- Show a more detailed tooltip (includes some calendar information) when hovering over the control
- UseLargePNGPresenceImages
- When set to true, the Persona control uses 24x24 images to display presence
- If not set, the control uses the small 16x16 images to display presence
- UseXAMLPresenceImages
- The control displays presence using vector images instead of PNGs
- CustomMenuItemList
- Allows you to extend the control's context menu with custom menu items
- Can only be set in code behind
As you can see, some of these properties are mutually exclusive. For example if set to True, UseXAMLPresenceImages would override UseLargePNGPresenceImages.
Most of the properties can be set either declaratively in XAML, or in the code behind.
By default, when you drop a Persona control into your XAML, none of its properties are specified (they default to false).
When UseXAMLPresenceImages is set to True, the presence images are rendered using vector images. The Persona control is them only bound by the size of the item containing it.
Oh yeah, big presence.
PersonaList
The PersonaList is simply a list of Persona controls, you can use this to display the presence and availability of a set of users.
The PersonaList exposes a SipUris property of type List<String>, you can set this property in your code behind:
The PersonalList control exposes all the properties exposed by PersonaList except for UseXAMLPresenceImages and SipUri (which is replaced by SipUris).
Out of the box, the PersonaList looks pretty bland. However, using the Persona control, you can build your own PersonaList that has its own specific look and feel, e.g. a hover and selected style. Gotta love WPF.
You can set the properties exposed by the underlying Persona control to whatever you like, e.g. you might not want to have a tooltip on the Persona control in your implementation of PersonaList.
MyPersona
The last control is the MyPersona control, which displays the availability and status of the currently signed in user. The developer isn't able to set the user that this control is bound to.
The little arrow exposes a context menu that the user can use to change their status, similar to how you can do this in the main Office Communicator window.
Custom Context Menu Items
The Persona control's (and PersonaList) context menu can be extended to include custom menu items defined by the developer. I'll leave that for another blog post, but there's a good example in the sample application that's available with the source code.
Non-Contacts
Nothing is there to stop you from pointing a Persona control at a contact that is not on your contact list. Office Communicator caches the presence of such contacts, and may show you their presence initially. However, it will not get presence update events for contacts not on your list.
To be specific, there is no guarantee that a ContactStatusChange event will be raised for a contact that is not on your contact list.
This is a security feature intended to prevent people from seeing the presence and availability of contacts not on their list. However, the controls seem to get presence updates correctly if the contact was previously in the contact list.
We made a design tradeoff to "gray out" presence icons for contacts that are not on the current user's contact list. We went with this approach because Office Communicator seemed inconsistent as to which contacts (not on the user's list) it would show correct presence for.
An important thing to note is that since Communicator allows you to add distribution lists as contacts. Members of those distribution lists are not in your contact list by default.
Feedback
I hope you find these controls useful. It seems that until now, the only other good option was to host the old Windows Forms Presence Controls in WPF.
If you have any feedback for improvement, or come across a bug or issue, please contact me.
Back in June at TechEd in Orlando, we demo'd an Office Communicator Vista gadget in the Unified Communications booth. I also had a breakout session in which we discussed how to build Vista gadgets using WPF and where we went through the gadget and the tools and techniques that we used to build it.
We've gotten the ok to put the project out on CodePlex, you can now download it at http://www.codeplex.com/MOCVistaGadget.
The CodePlex project includes all the source code, as well as a .gadget file that you can use to install the gadget into the Vista Sidebar.
Functionality
Connect to Exchange Web Services
The gadget uses Exchange Web Services to interact with your organization's Exchange Server. It uses EWS to check and retrieve your voicemail, and also to help track who your Top 5 contacts are.
By default, the gadget uses Autodiscover to figure out your Exchange Web Services connectivity details. You can alternatively specify a server address manually.
Top 5 Contacts
This screen allows you to configure the metrics that the gadget will use to track the Top 5 contacts that you interact with.
Favorite 5 Contacts
The gadget allows you to maintain 5 favorite contacts, these contacts can either be people or phone numbers.
You can add contacts in several ways:
- Drag a contact from your Office Communicator contact list into an empty Favorite 5 slot
- Type a contact's Sip URI into an empty Favorite 5 slot
- Type a contact's name into an empty Favorite 5 slot
- Type a phone number into an empty Favorite 5 slot
Once you have added a contact to your Favorite 5, you can also change its display name.
After adding contacts to your Favorite 5, you can specify a default click action for when you double-click the contact in the main gadget window. The available options are:
- Instant Message
- Phone Call
- Communicator Call
By default, the default click action for a phone number contact can only be a phone call.
Voicemail
If your organization uses Office Communications Server as your phone system, the gadget will poll your Exchange Server to check if you have new voicemail.
If you have new voicemail, the gadget displays a "new voicemail" indicator.
Clicking the voicemail icon opens a screen which lists all your voice mails, and indicates whether an individual voicemail has been read. Double-clicking a voicemail will open it in Outlook Web Access.
How we built it
The gadget uses the Office Communicator SDK to automate functions of Microsoft Office Communicator. The SDK is available as a COM object, and most of its functionality is not available via JavaScript.
We built the gadget as a XBAP application using WPF, allowing us to use the full functionality of the Office Communicator SDK, and also giving us a great development/debugging experience using IE since XBAP applications typically run in Internet Explorer.
The XBAP application is published into a ClickOnce manifest that is packaged into the gadget. Essentially, we tricked the Vista Sidebar into hosting an XBAP application within the gadget.
Packaging the XBAP Application into the Gadget
A gadget is simply a zip archive (but with a .gadget extension) containing a specific set of required files contained in it. For example, the gadget manifest - gadget.xml - specifies what the default page of the gadget should be.
In default.html, we simply iframe the XBAP into the web page. There's some trickeration involved in getting the margins right, the magic to make it work is in default.html and in Gadget.xaml.
Known Issues
UAC
The gadget uses the Office Communicator SDK for all Office Communicator automation functionality, the dll for the SDK is bundled into the ClickOnce manifest that is packaged into the gadget. In Windows Vista (pre-SP1), the code can only use the Office Communicator SDK COM object when UAC is turned *ON*. Vista SP1 is supposed to resolve this issue, but we have seen inconsistent behavior with that.
Internet Explorer 8
Since the gadget is essentially running an XBAP application, PresentationHost.exe is used to host it within IE. Some issues with the gadget hanging were reported when using IE8.
Opportunities for Improvement
I entered some issues in CodePlex which I'll get around to when I get some more time to work on improving. Please contact me if you have any feedback for improvement, or come across an issue or bug.
Today I published Release 1.0.0.4 of the OCSDKWrapper project on CodePlex.
A couple of people at Clarity have had the chance to use the OCSDKWrapper on some Communicator projects and were able to give me some great feedback for some enhancements. If you've had a chance to use the project and have any feedback, please let me know.
The biggest piece of feedback I got was that a developer couldn't access the underlying OCSDK objects via OCSDKWrapper.MOCAutomation, e.g. instances of MessengerClass, IMessengerAdvanced, MessengerPrivClass, and IMessengerContactResolution.
Doing this would allow the developer to use these underlying projects to code functionality not provided in the OCSDKWrapper. These objects are now exposed as public properties: