Silverlight presence indicator

A while back I published a Silverlight presence indicator control on CodePlex and I thought I’d explain this in more detail here.

The control is nothing more than an integration with the standard OCS presence indicator that comes with Microsoft Office (using Name.dll made famous by SharePoint sites). The integration is done using the Silverlight HTML bridge and javascript.

It’s all very simple and straightforward; the control injects javascript into the page where your Silverlight application is hosted and using these scripts it instantiates a new ActiveX object as well as hooking up the OnStatusChanged event.

if(!IMControl){{ IMControl = new ActiveXObject(\"Name.NameCtrl.1\");

IMControl.OnStatusChange=OCSOnStatusChange;

The function called when the ActiveX object fires a status change event will the use the HTML bridge to call a method in the Silverlight control to update the indicator icon.

function OCSOnStatusChange(name, state, id) {

  eval('{0}.Content.' + callbacks[id] + '.UpdateImage(' + state + ',\"'+ name +'\");');
}

This is made possible by registering the Silverlight control as a scriptable object so it can be called from Javascript.

HtmlPage.RegisterScriptableObject(objectName, this);

The UpdateImage method is the tagged as a ScriptableMember, otherwise it won’t be exposed to the HTML bridge.

[ScriptableMember()]
public void UpdateImage(object state, object name) {
    int stateValue = Int32.Parse(state.ToString());
    string imgName = GetStateIndicatorImage(stateValue, true);
    indicator.Source = new BitmapImage(new Uri(string.Format("/Silverlight.OCS;component/Images/{0}", imgName), UriKind.Relative));
    FireStatusChanged(name as string, stateValue);
}

Now, to get the ActiveX object to display the Communicator panel (where you can initiate chat sessions, see details, etc) we will use the HTML bridge to go in the other direction: From Silverlight to Javascript.

Among the Javascript functions we’ve injected into the page is the OCSOpenUI function, which we will call from Silverlight when we receive the MouseOver event on the indicator icon.

function OCSOpenUI(user, x, y) {    if(IMControl){       IMControl.ShowOOUI(user, 0, x, y);    } }

To call this function, all we need to do is invoke it:

HtmlPage.Window.Invoke("OCSOpenUI", User,x, y);

The coordinates are a bit tricky, as the Office 2010 Communicator panel will function just fine with the standard mouse coordinates. However, previous Office versions require that you locate the exact position of the Silverlight control then adjust for mouse coordinates. This involves using Javascript again to find the location of the control within the HTML page.

if (OfficeVersionCompatibility == Version.Office2007AndOlder) {
    ScriptObject result = (ScriptObject)HtmlPage.Window.Invoke("findPos", HtmlPage.Document.GetElementById(HtmlPage.Plugin.Id));
    int left = Int32.Parse(result.GetProperty("Left").ToString());
    int top = Int32.Parse(result.GetProperty("Top").ToString());
    Point posOnIcon = e.GetPosition(indicator);
    x = left + (int)(pos.X - posOnIcon.X);
    y = top + (int)(pos.Y - posOnIcon.Y);
}

 

In closing…

I’ve skipped a lot of steps here as the source code is freely available and should be fairly easy to understand. Should there be any questions, I’ll be more than happy to explain it in more detail 🙂 Also, should anyone have a better way of doing this, I’d appreciate some feedback.

You can find a compiled version of the control and the source code available here: CodePlex

Advertisements

11 Responses to Silverlight presence indicator

  1. K Cavitt says:

    Easy to use. This is great. I’m building a org chart in silverlight and using this control in my nodes to show presence.

    This will not work in FireFox. Lucky for me IE is our corp supported browser.

  2. K Au says:

    I am able to successfully use the control in a Silverlight app. However, it is not updating the status image when I change my status in Communicator 2007. For some reason, the Name.NameCtl.1 control’s OnStatusChange event is not firing the OCSOnStatusChange function. I debugged the javascript IMControl.OnStatusChange, IE says it is not a defined property. Can you please shed some light on this. Thanks.

    • Frode Hus says:

      I’ve never encountered this issue before, what Office version are you using? I tested this with Office 2007 and 2010, but not 2003 (not sure if the control exists there, though)

  3. X says:

    I have the same problem as K, can you provide any help ont his problem ?

  4. Q says:

    I’m using the control in a itemtemplate control databound to a collection of SIP values.

    I find that the presence icons dont seem to reflect the correct presence vaues, sometimes when i hover over the icon, i see the popup presence as being correct, but the indicator item is not, sometimes hovering over will trigger the value to change, but the image is updated on the wrong presence icon, ie the wrong user is updated?

    any ideas?

    Silvelright 4 app, and running MOC 2007, ver 2.0.6362.129

    Thanks.

    • Frode Hus says:

      I’ve seen this in some cases and unfortunately I don’t have any answer…
      As far as I can guess, it seems to be an issue with the html bridge not getting events from the javascript object.

      • Q says:

        I did a work around for this issue, my app is a prism applicaiton, i publish the update of the presence on the event aggregator and the presendicator subscribes to the event for their specific user to update the image, this is all done on a background thread for perfomance, only the update of the image is done on the UI thread.

        As far as i could work out, seems to be some type of race condition with respect to the JS bridge. In debug mode and steeping through the code most of the time the images would update, but running the app only the last image would update. By publishing the messages on the event aggregator i get around this by ensuring i don’t loose any update messages.

  5. John says:

    Hi! I need to incorporate office communicator info my silverlight application, but as my application is touch based, I find that the Office 2010 Communicator panel is not well suited. Do you have any experience with creating a custom menu for initiating office communicator conversations? Do you know if it is at all possible?

    • Frode Hus says:

      There is no way of doing that as far as I know, the ActiveX control that’s being used has a very limited interface and can basically only be used to get presence updates and launch the communicator panel. But the next version of OCS should be more open for Silverlight development unless I’m mistaken.

  6. beameup says:

    Great job.

    I was about to write something like this for my project, then did a search and … much time saved. Thanks for sharing.

    Note: Rather than passing in the javascript object reference to the silverlight control, you could clean it up a little by using the HtmlPage.PlugIn from within Silverlight to give you the JS object handle (then if necessary dynamically render it back to JS from Silverlight).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: