Conversation window docking within a WPF form requires the same programming steps as used to dock conversation window in a Windows Form. In addition, steps include embedding a WindowsFormsHostin your XAML document. This host control becomes the parent of the conversation window to be docked.
Important |
---|
If you create a Silverlight application, you must make all Microsoft Lync 2010 API calls on your UI thread. Lync 2010 API events are raised on the API thread. To update your UI controls from event handlers for these events, you use Dispatcher.Invoke to call methods on your UI thread and pass relevant event data to those UI thread methods. |
This walkthrough introduces the walkthrough steps required to enable your application to accept an incoming conversation as well as initiating a conversation.
Creating the Conversation Window Docking WPF Application
This example accepts an incoming conversation. To do this, the
example uses an instance of
To create a conversation window docking application using WPF, you add a WindowsFormsHostelement to your XAML document. For information about hosting a Windows Forms Control in your WPF application, see Walkthrough: Hosting a Windows Forms Control in WPF by Using XAML.
The
To create the IM conversation window docking Windows Forms Host Control
-
Sign in to Microsoft Lync 2010.
-
Add a reference to Microsoft.Lync.Model in your project reference folder. Browse to the C:\Program Files\Microsoft Lync\SDK\Assemblies\WPF\ folder and choose Microsoft.Lync.Model.dll.
-
Create a new class that calls the Lync API and handles events raised by the API.
Copy Code using System; using System.Collections.Generic; using System.Text; using Microsoft.Lync.Model; using Microsoft.Lync.Model.Conversation; using Microsoft.Lync.Model.Extensibility; namespace WPFDockingExample { public delegate void NewConversationDelegate(string NewConversationId); public delegate void ConversationRemovedDelegate(); public delegate void ConversationWindowNeedsAttentionDelegate(); public delegate void ConversationWindowNeedsSizeChangeDelegate(int newHeight, int newWidth); class AppLyncModel { public event NewConversationDelegate NewConversationEvent; public event ConversationWindowNeedsAttentionDelegate ConversationWindowNeedsAttentionEvent; public event ConversationWindowNeedsSizeChangeDelegate ConversationWindowNeedsSizeChangedEvent; public event ConversationRemovedDelegate ConversationRemoveEvent; LyncClient myLyncClient; Automation myAutomation; Dictionary<string, Conversation> myNewConversation; /// <summary> /// Docks a ConversationWindow in a Windows Forms Control associated with passed handle. /// </summary> /// <param name="ConversationId">string. Id of conversation to be docked.</param> /// <param name="PanelHandle">int. Handle of Windows Form Control to dock the conversation within.</param> public void WindowPanelHandle(string ConversationId, int PanelHandle) { Conversation conversationToDock; if (myNewConversation.TryGetValue(ConversationId, out conversationToDock)) { ConversationWindow cw = myAutomation.GetConversationWindow(conversationToDock); cw.NeedsAttention += cw_NeedsAttention; cw.NeedsSizeChange += cw_NeedsSizeChange; cw.Dock(PanelHandle); } } /// <summary> /// Raised when the ConversationWindow instance requires the parent control to change its size. /// </summary> /// <param name="sender">object. The ConversationWindow instance raising the event.</param> /// <param name="e">ConversationWindowNeedsSizeChangeEventArgs. The event state data.</param> void cw_NeedsSizeChange(object sender, ConversationWindowNeedsSizeChangeEventArgs e) { if (ConversationWindowNeedsSizeChangedEvent != null) { ConversationWindowNeedsSizeChangedEvent(((Conversation)sender).Properties[ConversationProperty.Id].ToString(), e.RecommendedWindowHeight, e.RecommendedWindowWidth); } } /// <summary> /// Raised when the parent of the docked ConversationWindow should get focus. /// </summary> /// <param name="sender">object. The ConversationWindow instance raising the event.</param> /// <param name="e">ConversationWindowNeedsAttentionEventArgs. The event state data.</param> void cw_NeedsAttention(object sender, ConversationWindowNeedsAttentionEventArgs e) { if (ConversationWindowNeedsAttentionEvent != null) { ConversationWindowNeedsAttentionEvent(((Conversation)sender).Properties[ConversationProperty.Id].ToString()); } } /// <summary> /// Raised when a conversation is ended. /// </summary> /// <param name="sender">object. The ConversationManager.</param> /// <param name="e">ConversationManagerEventArgs. The Event state data.</param> void ConversationManager_ConversationRemoved(object sender, ConversationManagerEventArgs e) { if (ConversationRemoveEvent != null) { ConversationRemoveEvent(((Conversation)sender).Properties[ConversationProperty.Id].ToString()); } } /// <summary> /// Raised when a new conversation is added to the Conversations collection of the ConversationManager instance. /// </summary> /// <param name="sender">object. The ConversationManager.</param> /// <param name="e">ConversationManagerEventArgs. The Event state data.</param> void ConversationManager_ConversationAdded(object sender, ConversationManagerEventArgs e) { if (NewConversationEvent != null) { myNewConversation.Add(e.Conversation.Properties[ConversationProperty.Id].ToString(), e.Conversation); NewConversationEvent(e.Conversation.Properties[ConversationProperty.Id].ToString()); } } /// <summary> /// Class constructor. /// </summary> public AppLyncModel() { myLyncClient = LyncClient.GetClient(); if (myLyncClient.State != ClientState.SignedIn) { throw new Exception("Lync is not signed in"); } myNewConversation = new Dictionary<string, Conversation>(); myAutomation = Microsoft.Lync.Model.LyncClient.GetAutomation(); myLyncClient.ConversationManager.ConversationAdded += ConversationManager_ConversationAdded; myLyncClient.ConversationManager.ConversationRemoved += ConversationManager_ConversationRemoved; } } }
-
In your WPF application, open your MainWindow.XAML source and add the following attribute to the WindowXAML element.
Copy Code xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
-
Add a WindowsFormsHostand Panelelement and within the Windows Forms host
Copy Code <WindowsFormsHost> <wf:Panel Name="ConversationPanel" /> </WindowsFormsHost>
-
Add the following code to the MainWindow.xaml.cs file inside the namespace declaration and before the class declaration. These delegate declarations allow the example to marshal event data to the main UI thread from within the Lync client thread.
Copy Code delegate void DockConversationDelegate(string ConversationId); delegate void ResizeConversationDelegate(int newHeight, int newWidth); delegate void FocusConversationPanelDelegate(string ConversationId); delegate void HideConversationPanelDelegate();
-
Add the following code to the MainWindow.xaml.cs file to declare an instance of the class you create in step 1.
Copy Code AppLyncModel _LyncModel;
-
Add the following code to the MainWindow constructor. This example code instantiates an instance of a custom class found in step 1 and then registers for events related to the conversation window to be docked within the WPF page.
Copy Code _LyncModel = new AppLyncModel(); _LyncModel.NewConversationEvent += _LyncModel_NewConversationEvent; _LyncModel.ConversationRemoveEvent += _LyncModel_ConversationRemoveEvent; _LyncModel.ConversationWindowNeedsAttentionEvent += _LyncModel_ConversationWindowNeedsAttentionEvent; _LyncModel.ConversationWindowNeedsSizeChangedEvent += _LyncModel_ConversationWindowNeedsSizeChangedEvent;
-
Add the following methods to the MainWindow class. The events handled by these methods are raised by the AppLyncModel class found in the first step.
Copy Code /// <summary> /// Called by AppLyncModel when a new conversation has been created. /// </summary> /// <param name="NewConversationId">string. Id of new conversation.</param> void _LyncModel_NewConversationEvent(string NewConversationId) { ConversationPanel.Invoke(new DockConversationDelegate(DockTheConversation), new object[] { NewConversationId }); } /// <summary> /// Called by AppLyncModel when the docked conversation window size changes /// </summary> /// <param name="newHeight">int. The new recommended height of the WPF page</param> /// <param name="newWidth">int. The new recommended width of the WPF page</param> void _LyncModel_ConversationWindowNeedsSizeChangedEvent(int newHeight, int newWidth) { this.Dispatcher.Invoke(new ResizeConversationDelegate(ResizePage), new object[] {newHeight+10, newWidth+10 }); } /// <summary> /// Called by AppLyncModel when there is activity in the conversation window. /// </summary> void _LyncModel_ConversationWindowNeedsAttentionEvent() { ConversationPanel.Invoke(new FocusConversationPanelDelegate(FocusThePage), new object[] { }); } /// <summary> /// Called by AppLyncModel when the conversation has ended. /// </summary> void _LyncModel_ConversationRemoveEvent(string ConversationToRemoveId) { ConversationPanel.Invoke(new HideConversationPanelDelegate(HideConversationPanel), new object[] { ConversationToRemoveId }); } /// <summary> /// Invoked on UI thread when a new conversation has been added and needs to be docked. /// </summary> /// <param name="ConversationId">string. Id of new conversation.</param> private void DockTheConversation(string ConversationId) { _LyncModel.WindowPanelHandle(ConversationId, ConversationPanel.Handle.ToInt32()); } /// <summary> /// Invoked on UI thread when a conversation has ended. /// </summary> private void HideConversationPanel(string ConversationId) { ConversationPanel.Hide(); this.Height = 350; this.Width = 525; } /// <summary> /// Invoked on UI thread when WPF page needs focus. /// </summary> private void FocusThePage() { this.Focus(); } /// <summary> /// Invoked on UI thread when WPF page needs size change. /// </summary> /// <param name="newHeight">int. New recommended height of page.</param> /// <param name="newWidth">int. New recommended width of page.</param> private void ResizePage(int newHeight, int newWidth) { this.Height = newHeight; this.Width = newWidth; }
-
Press F5 to build and run the application.