Implementing XamSchedule Solution in Silverlight Applications Using a WcfListDataConnector

[Infragistics] Mihail Mateev / Saturday, October 30, 2010

XamSchedule suite offers a WcfScheduleDataConnector to use a data from different sources via WCF service.

It is very easy to create a multi user applications that have calendar or other scheduling features.
When schedule application uses a data on a remote server the best approach is to use WcfScheduleDataConnector instead ListScheduleDataConnector.
In this case connector will be responsible for communication between client and server side. Otherwise using a ListScheduleDataConnector developers must implement this functionality.

The WcfListScheduleDataConnector offers two classes for WCF Service on the server side: WcfListConnectorServiceSingle and WcfListConnectorServiceMulti.
A WcfListConnectorServiceSingle provides list schedule data to the client. Only one instance of this service class will be created and all remote calls will be run on the same thread. This reduces overhead on each remote call, but because of this, this service should only be used when it is known that a relatively small number of clients will be connecting to the service. If there too many clients or timeouts when using  WcfListConnectorServiceSingle the WcfListConnectorServiceMulti is recommended.
In the sample is used a WCF service which provides list schedule data to the client. WCF service class, named Test2008DataService inherits WcfListConnectorServiceMulti class to demonstrate an application with more clients, connected to the service. A new instance of this service will be created for each remote call into the service and calls may be made on different threads. Data sources provided to this service are thread safe.

There are three important moments:

  • Project database to have corresponding data types to Resource ResourceCalendar and Activity (Appointment, Task, Journal) properties.
    Otherwise, you need to implement your own data conversion before filed mapping.
  • Methods override in WcfListConnectorServiceMulti inheritor.
  • Set an EndPoint in the client configuration file:
    The remote WCF service can be specified in two different ways. A service endpoint can be defined in a configuration file or the remote address and binding can be specified directly on the connector. The easiest way to define the location of a remote WCF service and use it in multiple clients in an application is to define an endpoint in the configuration file (ServiceReferences.ClientConfig) and set to WcfListScheduleDataConnector.EndpointConfigurationName the name of the endpoint configuration .

Demo application will demonstrate a simple way to start with a multi user scheduling application, that uses a SQL Server 2008 database and a WcfListConnectorServiceMulti .

Requirements:

  1. NetAdvantage for Silverlight  Line of Business 2010 Vol.3
  2. NetAdvantage for .NET 2010 Vol.3
  3. NetAdvantage Ultimate 2010 Vol.3

Steps to reproduce a demo application.

  • Download Test2008R2 database and attach it to SQL Server 2008 R2 (Express or higher license)
  • Create a Silverlight Application, hosted in ASP.Net web application.
  • Add a reference to Infragistics4.Services.Schedules.WcfConnectorService.v10.3 in the web project.
  • Add a new LINQ to SQL Classes mapped to the relational objects Resources, ResourceCalendars, Appointments, Tasks and Journals.
  • Add a WCF Service named Test2008DataService in the Web project that inherits WcfListConnectorServiceMulti.
  • Override these methods on Test2008DataService class (including mapping fields):

    GetItemSource
    InitializePropertyMappings
    OnRemoteCallReceived
    OnRemoteCallProcessed
    OnActivityAdded
    OnActivityChanged
    OnActivityRemoved

  • Set endpoint in the Web.Config
  • Define an endpoint in the configuration file (ServiceReferences.ClientConfig)
  • Add a WcfListScheduleDataConnector in the Silverlight Application.
  • Set to WcfListScheduleDataConnector.EndpointConfigurationName the name of the endpoint configuration
  • Add a XamScheduleDataManager.
  • Add UI components from Schedule Suite: XamDayView, XamScheduleView, XamMonthView
  • Implement a multi resource and multi calendar support.
  • Implement a runtime change of the view type
  • Implement a runtime support for calendar display mode.
  • Run the application.

 

 

Download Test2008R2 database and attach it to SQL Server 2008 R2 (Express or higher license)

Download Test2008R2  database, extract it and attach it to your SQL Server

 

Create a Silverlight Application, hosted in ASP.Net web application

Create a Silverlight Application, hosted in ASP.Net web application and named XamScheduleWCFService.

 

Add a reference to Infragistics4.Services.Schedules.WcfConnectorService.v10.3 in the web project.

 

Add a new LINQ to SQL Classes mapped to the relational objects Resources, ResourceCalendars, Appointments, Tasks and Journals.

Add a new LINQ to SQL Classes, named Test2008R2DataClasses mapped to the relational objects Resources , ResourceCalendars, Appointments, Tasks and Journals.

  

 

Override the methods on Test2008DataService class:

GetItemSource:

   1: private Test2008R2DataClassesDataContext dataContext;
   2:  
   3:         protected override IEnumerable GetItemSource(ItemSourceType listManagerType)
   4:         {            
   5:             switch (listManagerType)
   6:             {
   7:                 case ItemSourceType.Appointment:
   8:                     return this.dataContext.Appointments;
   9:  
  10:                 case ItemSourceType.RecurringAppointment:
  11:                     return null;
  12:  
  13:                 case ItemSourceType.Resource:
  14:                     return this.dataContext.Resources;
  15:  
  16:                 case ItemSourceType.ResourceCalendar:
  17:                     return this.dataContext.ResourceCalendars;
  18:  
  19:             }
  20:  
  21:             return null;
  22:         }

 

InitializePropertyMappings – there is implemented fields mapping.

   1: protected override void InitializePropertyMappings(ItemSourceType itemSourceType, object mappings)
   2: {
   3:     switch (itemSourceType)
   4:     {
   5:         case ItemSourceType.Appointment:
   6:             ((AppointmentPropertyMappingCollection)mappings).UseDefaultMappings = true;
   7:             break;
   8:  
   9:         case ItemSourceType.RecurringAppointment:
  10:             ((AppointmentPropertyMappingCollection)mappings).UseDefaultMappings = true;
  11:             break;
  12:  
  13:         case ItemSourceType.Resource:
  14:             ((ResourcePropertyMappingCollection)mappings).UseDefaultMappings = true;
  15:             break;
  16:  
  17:         case ItemSourceType.ResourceCalendar:
  18:             ((ResourceCalendarPropertyMappingCollection)mappings).UseDefaultMappings = true;
  19:             break;
  20:  
  21:     }
  22: }

 

OnRemoteCallReceived

   1: protected override void OnRemoteCallReceived(CallContext context)
   2: {
   3:     this.dataContext = new Test2008R2DataClassesDataContext();
   4:     base.OnRemoteCallReceived(context);
   5: }

 

OnRemoteCallProcessed

   1: protected override void OnRemoteCallProcessed(CallResult result)
   2: {
   3:     base.OnRemoteCallProcessed(result);
   4:  
   5:     this.dataContext.Dispose();
   6:     this.dataContext = null;
   7: }

 

OnActivityAdded

   1: protected override void OnActivityAdded(ActivityAddedEventArgs args)
   2: {
   3:     base.OnActivityAdded(args);
   4:     this.dataContext.SubmitChanges();
   5: }

OnActivityChanged

   1: protected override void OnActivityChanged(ActivityChangedEventArgs args)
   2: {
   3:     base.OnActivityChanged(args);
   4:     this.dataContext.SubmitChanges();
   5: }

OnActivityRemoved

   1: protected override void OnActivityRemoved(ActivityRemovedEventArgs args)
   2: {
   3:     base.OnActivityRemoved(args);
   4:     this.dataContext.SubmitChanges();
   5: }

 

Set endpoint in the Web.Config

Check the Web.Config file to ensure that the endpoint for WCF service is properly set, You need to have a contract from type: Infragistics.Services.Schedules.IWcfListConnectorService.

   1: <?xml version="1.0"?>
   2:  
   3: <!--
   4:   For more information on how to configure your ASP.NET application, please visit
   5:   http://go.microsoft.com/fwlink/?LinkId=169433
   6:   -->
   7:  
   8: <configuration>
   9:     <connectionStrings>
  10:         <add name="Test2008R2ConnectionString" connectionString="Data Source=.\SQLExpress;Initial Catalog=Test2008R2;Integrated Security=True"
  11:             providerName="System.Data.SqlClient" />
  12:     </connectionStrings>
  13:     <system.web>
  14:         <compilation debug="true" targetFramework="4.0" />
  15:     </system.web>
  16:  
  17:     <system.serviceModel>
  18:         <behaviors>
  19:             <serviceBehaviors>
  20:                 <behavior>
  21:                     <serviceMetadata httpGetEnabled="true" />
  22:                     <serviceDebug includeExceptionDetailInFaults="false" />
  23:                 </behavior>
  24:             </serviceBehaviors>
  25:         </behaviors>
  26:       <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  27:         <bindings>
  28:             <customBinding>
  29:                 <binding name="CustomBinding1">
  30:                   <binaryMessageEncoding>
  31:                     <readerQuotas maxStringContentLength="2147483647" />
  32:                   </binaryMessageEncoding>
  33:                   <httpTransport authenticationScheme="Anonymous" />
  34:                 </binding>              
  35:             </customBinding>
  36:         </bindings>
  37:         <services>
  38:             <service name="XamScheduleWCFService.Web.Test2008DataService">
  39:                 <endpoint address="" binding="customBinding" bindingConfiguration="CustomBinding1"
  40:                     contract="Infragistics.Services.Schedules.IWcfListConnectorService" />
  41:                 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  42:             </service>
  43:         </services>
  44:     </system.serviceModel>
  45:   <system.webServer>
  46:     <modules runAllManagedModulesForAllRequests="true"/>
  47:   </system.webServer>
  48: </configuration>

 

Define an endpoint in the configuration file (ServiceReferences.ClientConfig)

Modify your ServiceReferences.ClientConfig file (if you have no ServiceReferences.ClientConfig – create it follow the sample below):

   1: <configuration>
   2:   <system.serviceModel>
   3:     <bindings>
   4:       <customBinding>
   5:         <binding name="MyCustomBinding">
   6:           <binaryMessageEncoding />
   7:           <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
   8:         </binding>
   9:       </customBinding>
  10:     </bindings>
  11:     <client>
  12:       <endpoint address="http://localhost:41558/Test2008DataService.svc"
  13:         binding="customBinding" bindingConfiguration="MyCustomBinding"
  14:         contract="WcfListConnectorServiceSL.IWcfListConnectorService"
  15:         name="MyEndpointConfigurationSQL" />      
  16:     </client>
  17:   </system.serviceModel>
  18: </configuration>

 

Add a WcfListScheduleDataConnector in the Silverlight Application.

   1: <ig:WcfListScheduleDataConnector 
   2:             Name="DataConnector" />

 

Set to WcfListScheduleDataConnector.EndpointConfigurationName the name of the endpoint configuration

Set in XAML defined in ServiceReferences.ClientConfig endpoint to WcfListScheduleDataConnector.EndpointConfigurationName

   1: <ig:WcfListScheduleDataConnector 
   2:             Name="DataConnector"
   3:             EndpointConfigurationName="MyEndpointConfigurationSQL"
   4:             PollingInterval="00:00:10"
   5:             PollingMode="Detailed" Loaded="DataConnector_Loaded"  
   6:             />

 

Add a XamScheduleDataManager.

   1: <ig:XamScheduleDataManager Name="DataManager" CurrentUserId="mdour"  DataConnector="{Binding ElementName=DataConnector}" >
   2:      <ig:XamScheduleDataManager.Settings>
   3:          <ig:ScheduleSettings>
   4:              <ig:ScheduleSettings.AppointmentSettings>
   5:                  <ig:AppointmentSettings AllowEdit="True"  AllowResizing="StartAndEnd"/>
   6:              </ig:ScheduleSettings.AppointmentSettings>
   7:          </ig:ScheduleSettings>
   8:      </ig:XamScheduleDataManager.Settings>
   9:  </ig:XamScheduleDataManager>

 

Add UI components from Schedule Suite: XamDayView, XamScheduleView, XamMonthView

   1: <ig:XamDayView Grid.Row="1" Name="xamDayView1" Margin="5" BorderBrush="Black" MultiDayActivityAreaVisibility="Collapsed"
   2:                               DataManager="{Binding ElementName=DataManager}" ActiveCalendarChanged="DayView_ActiveCalendarChanged"
   3:                                />
   4:         <ig:XamScheduleView HorizontalAlignment="Stretch" Grid.Row="1" Name="xamScheduleView1" VerticalAlignment="Stretch" 
   5:                             DataManager="{Binding ElementName=DataManager}" Visibility="Collapsed" />
   6:         <ig:XamMonthView HorizontalAlignment="Stretch"  Grid.Row="1" Name="xamMonthView1" VerticalAlignment="Stretch" 
   7:                             DataManager="{Binding ElementName=DataManager}" Visibility="Collapsed" />

 

Implement a multi resource and multi calendar Support.

Two methods are added in the MainPage: SetAllCalendars  and SetResource


SetAllCalendars displays the calendars of all resources.

   1: #region SetAllCalendars
   2: private void SetAllCalendars()
   3: {
   4:     this.DataManager.CalendarGroups.Clear();
   5:     foreach (Resource resource in this.DataManager.ResourceItems)
   6:     {
   7:  
   8:         if (resource != null)
   9:         {
  10:             CalendarGroup group = new CalendarGroup();
  11:  
  12:  
  13:             foreach (ResourceCalendar calendar in resource.Calendars)
  14:             {
  15:                 if (calendar != null)
  16:                 {
  17:                     group.Calendars.Add(calendar);
  18:                 }
  19:  
  20:             }
  21:  
  22:             this.DataManager.CalendarGroups.Add(group);
  23:         }
  24:  
  25:     }
  26:  
  27:     this.cboResources.SelectedIndex = -1;
  28:  
  29: }
  30: #endregion //SetAllCalendars

SetResource displays the calendar of specific resource.

   1: #region SetResource
   2: private void SetResource(Resource resource)
   3: {
   4:  
   5:     this.DataManager.CalendarGroups.Clear();
   6:  
   7:     CalendarGroup group = new CalendarGroup();
   8:  
   9:     foreach (ResourceCalendar calendar in resource.Calendars)
  10:     {
  11:         if (calendar != null)
  12:         {
  13:             group.Calendars.Add(calendar);
  14:         }
  15:  
  16:     }
  17:  
  18:     this.DataManager.CalendarGroups.Add(group);
  19: }
  20: #endregion //SetResource

 

Implement a runtime change of the view type

In the page layout is added a ListBox control with items for each view – day view, schedule view and month view.

   1: <ListBox x:Name="ListScheduleViews" Margin="5 0 5 0"   SelectionMode="Single"  SelectionChanged="ListScheduleViews_SelectionChanged">
   2:     <ListBox.ItemsPanel>
   3:         <ItemsPanelTemplate>
   4:             <StackPanel Orientation="Horizontal" Margin="0" />
   5:         </ItemsPanelTemplate>
   6:     </ListBox.ItemsPanel>
   7:     <ListBoxItem x:Name="DayViewItem" Content="Day View" Tag="DayView" Margin="0 0 10 0" IsSelected="True" />
   8:     <ListBoxItem x:Name="ScheduleViewItem" Content="Schedule View" Tag="ScheduleView" Margin="0 0 10 0" IsSelected="False" />
   9:     <ListBoxItem x:Name="MonthViewItem" Content="Month View" Tag="MonthView" Margin="0 0 10 0" IsSelected="False" />
  10: </ListBox>

 

When  the selection is changed , an event  calls an event handler that is changing the visibility of the three UI controls XamDayView, XamScheduleView and XamMonthView.

   1: #region ListScheduleViews_SelectionChanged
   2: private void ListScheduleViews_SelectionChanged(object sender, SelectionChangedEventArgs e)
   3: {
   4:     ListBoxItem item = e.AddedItems[0] as ListBoxItem;
   5:     if (item != null)
   6:     {
   7:         SetScheduleMode(item.Tag.ToString());
   8:     }
   9: }
  10: #endregion //ListScheduleViews_SelectionChanged
  11:  
  12: #region SetScheduleMode
  13: private void SetScheduleMode(string viewName)
  14: {
  15:     if (this.xamDayView1 == null || this.xamMonthView1 == null || this.xamScheduleView1 == null)
  16:     {
  17:         return;
  18:     }
  19:  
  20:     switch (viewName)
  21:     {
  22:         case "DayView":
  23:             this.xamDayView1.Visibility = System.Windows.Visibility.Visible;
  24:             this.xamMonthView1.Visibility = System.Windows.Visibility.Collapsed;
  25:             this.xamScheduleView1.Visibility = System.Windows.Visibility.Collapsed;
  26:             break;
  27:         case "ScheduleView":
  28:             this.xamDayView1.Visibility = System.Windows.Visibility.Collapsed;
  29:             this.xamMonthView1.Visibility = System.Windows.Visibility.Collapsed;
  30:             this.xamScheduleView1.Visibility = System.Windows.Visibility.Visible;
  31:             break;
  32:         case "MonthView":
  33:             this.xamDayView1.Visibility = System.Windows.Visibility.Collapsed;
  34:             this.xamMonthView1.Visibility = System.Windows.Visibility.Visible;
  35:             this.xamScheduleView1.Visibility = System.Windows.Visibility.Collapsed;
  36:             break;
  37:     }
  38: }
  39: #endregion //SetScheduleMode

 

Implement Runtime Support for Calendar Display Mode.

Changing the  Calendar Display Mode is described in article How to Use Infragistics XamSchedule Solution

Run the application:

Click on the “SecondaryCal” calendar.

Look at the calendar: the new appointment has added.

Resize the appointment to change end time and make a duration 1 hour.

Click on the calendar “MateevCal”, owned from mmateev resource.
Add a new appointment with a name “Blue Sheet meeting”.

Make the selected appointment recurrent.
In the activity dialog click on “Recurrence” button.
Set options in the Recurrence pattern: weekly recurrence each Friday. Add Range of recurrence “No end date”

Close the recurrence settings.

Now the last added appointment is recurrent.

Look at the sample database “Test2008R2”:
new appointments are added in the table “Appointments”.

 Change the calendar display mode to overlay.

Change the resources:
Change the current resource to “Mihail Mateev”.
Only calendars, owned from this user are visible.

Change the current resource to “Mike Dour”.

Click on “All users” Button to display all calendars for all resources
and change calendar display mode to “Separate”.

Change the view type to “Schedule View”.Change the view type to “Month View”.
All calendars are displayed now in a month view.

Demo application you could find here:

Sample data base could be downloaded here: