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 note 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 Microsoft.Lync.Model.Conversation . . :: . . ConversationManager and registers for the ConversationManager . . :: . . ConversationAdded event.

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 ConversationManager . . :: . . ConversationAdded event is raised by the Lync thread instead of the main UI thread. The example declares a delegate and marshals the event data to the UI thread by invoking the delegate on the UI thread. The delegated method actually docks the conversation window within the WindowsFormsHost.

To create the IM conversation window docking Windows Forms Host Control

  1. Sign in to Microsoft Lync 2010.

  2. 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.

  3. Create a new class that calls the Lync API and handles events raised by the API.

      Copy imageCopy 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;
    	}
    }
    }
    
    
  4. In your WPF application, open your MainWindow.XAML source and add the following attribute to the WindowXAML element.

      Copy imageCopy Code
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    
  5. Add a WindowsFormsHostand Panelelement and within the Windows Forms host

      Copy imageCopy Code
    		<WindowsFormsHost>
    			<wf:Panel Name="ConversationPanel" />
    		</WindowsFormsHost>
    
    
  6. 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 imageCopy Code
    	delegate void DockConversationDelegate(string ConversationId);
    	delegate void ResizeConversationDelegate(int newHeight, int
    newWidth);
    	delegate void FocusConversationPanelDelegate(string
    ConversationId);
    	delegate void HideConversationPanelDelegate();
    
    
    
  7. Add the following code to the MainWindow.xaml.cs file to declare an instance of the class you create in step 1.

      Copy imageCopy Code
    		AppLyncModel _LyncModel;
    
  8. 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 imageCopy Code
    		_LyncModel = new AppLyncModel();
    		_LyncModel.NewConversationEvent +=
    _LyncModel_NewConversationEvent;
    		_LyncModel.ConversationRemoveEvent +=
    _LyncModel_ConversationRemoveEvent;
    		_LyncModel.ConversationWindowNeedsAttentionEvent +=
    _LyncModel_ConversationWindowNeedsAttentionEvent;
    		_LyncModel.ConversationWindowNeedsSizeChangedEvent +=
    _LyncModel_ConversationWindowNeedsSizeChangedEvent;
    
    
  9. 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 imageCopy 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;
    	}
    
    
    
  10. Press F5 to build and run the application.

See Also