How to Use Infragistics XamSchedule Solution

[Infragistics] Mihail Mateev / Monday, October 25, 2010

Infragistics XamSchedule Solution is a part of  NetAdvatage 2010 Volume 3  products.

The new scheduling components are offered both for Silverlight and WPF.
XamSchedule suite for Silverlight is a part of NetAdvantage for Silverlight  Line of Business 2010 Vol.3, 
XamSchedule for WPF is a part of NetAdvantage for WPF Line of Business 2010 Vol.3.

Both suites are part of NetAdvantage for .NET 2010 Vol.3 and NetAdvantage Ultimate 2010 Vol.3.

This article is about how to start with Infragistics XamSchedule solution for Silverlight.
Both XamSchedule for Silverlight and XamSchedule for WPF have the same API.
There are only some small differences in usage, related with Silverlight and WPF frameworks.

XamSchedule Architecture:

XamSchedule solution proposes most of the Microsoft™ Outlook™ calendar functionality. It allows you to display activity information in different views with little code. It supports displaying multiple resources with multiple calendars.

The solution contains UI elements (views), a data manager control and data connectors.

Views:

There are three UI elements (views) in the solution: xamDayView, xamScheduleView and xamMonthView. They allow the user to display and manipulate activities  that are associated with calendars of one or more resources.

DataManager:

DataManager class provides the data (resources, calendars and activities) to views. It exposes properties that provide various settings, including working days, hours and settings that control user interaction.

Data Connectors:

Data Connectors are non-visual elements, used to bind to your schedule data (resources, calendars and activities). Each data connector is then associated with the data manager, which will provide a data for each of the view controls.

The following Data Connectors are provided:

  • ListScheduleDataConnector
  • WcfScheduleDataConnector


The List and WcfScheduleDataConnector classes support mapping of properties between data source objects and XamSchedule objects ( Resources, Calendars and Activities) to allow binding to a wide range of data sources.

The ListScheduleDataConnector is a non-visual element that is used as a connector between XamScheduleDataManager and a scheduling data source. It creates view model objects (resources, calendars and activities) that are provided to the schedule data manager. You can bind the connector to any set of IEnumerable item sources. The data is then manipulated in the UI via XamScheduleDataManager, which in turns directs the requests to the data connector. The data connector realizes the changes back to the underlying item sources.

The WcfScheduleDataConnector is used when the schedule user interface cannot easily access the data on demand and it is not practical to send all schedule data in a database from the server to the client. The WCF list connector communicates with a service that accepts IEnumerable collections on a server and sends back only the schedule data that is requested by the client.
In the client side WcfScheduleDataConnector  works with the XamScheduleDataManager in the similar way, like ListScheduleDataConnector. You need to set DataConnector property to an instance of WcfListScheduleDataConnector and telling that connector the location of the remote WCF service.

In addition, custom data connectors can be created to fulfill specific needs.
The Data Connector also supports specifying time zone information.

 

Sample XamSchedule Application:

Demo application demonstrates how to start with the XamSchedule suite. The most important to start is to set proper DataConnector settings properly.

The sample uses a  ListScheduleDataConnector. In the application solution is created ViewModel that proposes custom collections for Resources (users) , RecourceCalendar (calendars) and Appointments. ViewModel could receive data from different sources. This demo is focused on XamSchedule suite parts and
doesn’t implements server side storage for schedule data source.

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.

  • Create a Silverlight Application.
  • Create a View Model with Members for Resources, Resource Calendars and Appointments.
  • Add a ListScheduleDataConnector and Set the Mapping Fields.
  • Add a XamScheduleDataManager.
  • Add UI Components from Schedule Suite: XamDayView, XamScheduleView, XamMonthView
  • Implement a Multi Calendar Support.
  • Implement Runtime Support for Calendar Display Mode.
  • Implement persistence of the current XamSchedule Settings.
  • Handle TimeZone Options.

Create a Silverlight Application

Create a Silverlight application, named SilverlightXamScheduleApp. |
There is no need to host a Silverlight application in the ASP.Net Web  application. Demo project exposes XamSchedule features, related with views, XamScheduleDataManager and ListScheduleDataConnector.

Create a View Model with Members for Resources, Resource Calendars and Appointments.

Create three classes, named ResourceInfo, ResourceCalendarInfo and AppointmentInfo. These classes exposes properties, responding to the required properties
for Recource, RecourceCalendar and Appointment classes in XamSchedule suite. In this sample are used custom classes for data sources, exposed in the our ViewModel.

The ListScheduleDataConnector and WcfScheduleDataConnector classes support mapping of properties between data source objects and XamSchedule objects (e.g., Resources, Calendars and Activities) to allow binding to a wide range of data sources. This is described in "Mapping Fields in Your Backend Data Source” topic in documentation.

Here is a code for data source classes:

ResourceInfo class:

   1: public class ResourceInfo : BaseViewModel
   2:     {
   3:  
   4:         #region Properties
   5:  
   6:         #region DaySettingsOverrides
   7:         private string _daySettingsOverrides;
   8:  
   9:         public string DaySettingsOverrides
  10:         {
  11:             get { return _daySettingsOverrides; }
  12:             set
  13:             {
  14:                 _daySettingsOverrides = value;
  15:                 OnPropertyChanged("DaySettingsOverrides");
  16:             }
  17:         }
  18:         #endregion //DaySettingsOverrides
  19:  
  20:         #region DaysOfWeek
  21:         private string _daysOfWeek;
  22:  
  23:         public string DaysOfWeek
  24:         {
  25:             get { return _daysOfWeek; }
  26:             set
  27:             {
  28:                 _daysOfWeek = value;
  29:                 OnPropertyChanged("DaysOfWeek");
  30:             }
  31:         }
  32:         #endregion //DaysOfWeek
  33:  
  34:         #region Description
  35:         private string _description;
  36:  
  37:         public string Description
  38:         {
  39:             get { return _description; }
  40:             set
  41:             {
  42:                 _description = value;
  43:                 OnPropertyChanged("Description");
  44:             }
  45:         }
  46:         #endregion //Description
  47:  
  48:         #region EmailAddress
  49:         private string _emailAddress;
  50:  
  51:         public string EmailAddress
  52:         {
  53:             get { return _emailAddress; }
  54:             set
  55:             {
  56:                 _emailAddress = value;
  57:                 OnPropertyChanged("EmailAddress");
  58:             }
  59:         }
  60:         #endregion //EmailAddress
  61:  
  62:         #region FirstDayOfWeek
  63:         private Nullable<byte> _firstDayOfWeek;
  64:  
  65:         public Nullable<byte> FirstDayOfWeek
  66:         {
  67:             get { return _firstDayOfWeek; }
  68:             set
  69:             {
  70:                 _firstDayOfWeek = value;
  71:                 OnPropertyChanged("FirstDayOfWeek");
  72:             }
  73:         }
  74:         #endregion //FirstDayOfWeek
  75:  
  76:         #region Id
  77:         private string _id;
  78:  
  79:         public string Id
  80:         {
  81:             get { return _id; }
  82:             set
  83:             {
  84:                 _id = value;
  85:                 OnPropertyChanged("Id");
  86:             }
  87:  
  88:         }
  89:         #endregion //Id
  90:  
  91:         #region IsLocked
  92:         private string _isLocked;
  93:  
  94:         public string IsLocked
  95:         {
  96:             get { return _isLocked; }
  97:             set
  98:             {
  99:                 _isLocked = value;
 100:                 OnPropertyChanged("IsLocked");
 101:             }
 102:         }
 103:         #endregion //IsLocked
 104:  
 105:         #region IsVisible
 106:         private string _isVisible;
 107:  
 108:         public string IsVisible
 109:         {
 110:             get { return _isVisible; }
 111:             set
 112:             {
 113:                 _isVisible = value;
 114:                 OnPropertyChanged("IsVisible");
 115:             }
 116:         }
 117:         #endregion //IsVisible
 118:  
 119:         #region Name
 120:         private string _name;
 121:  
 122:         public string Name
 123:         {
 124:             get { return _name; }
 125:             set
 126:             {
 127:                 _name = value;
 128:                 OnPropertyChanged("Name");
 129:             }
 130:         }
 131:         #endregion //Name
 132:  
 133:         #region PrimaryCalendarId
 134:         private string _primaryCalendarId;
 135:  
 136:         public string PrimaryCalendarId
 137:         {
 138:             get { return _primaryCalendarId; }
 139:             set
 140:             {
 141:                 _primaryCalendarId = value;
 142:                 OnPropertyChanged("PrimaryCalendarId");
 143:             }
 144:         }
 145:         #endregion //PrimaryCalendarId
 146:  
 147:         #region PrimaryTimeZoneId
 148:         private string _primaryTimeZoneId;
 149:  
 150:         public string PrimaryTimeZoneId
 151:         {
 152:             get { return _primaryTimeZoneId; }
 153:             set
 154:             {
 155:                 _primaryTimeZoneId = value;
 156:                 OnPropertyChanged("PrimaryTimeZoneId");
 157:             }
 158:         }
 159:         #endregion //PrimaryTimeZoneId 
 160:  
 161:         #endregion //Properties
 162:     }

 

ResourceCalendarInfo class:

   1: public class ResourceCalendarInfo: BaseViewModel
   2: {
   3:  
   4:     #region Proeprties
   5:  
   6:     #region BaseColor
   7:     private Nullable<int> _baseColor;
   8:  
   9:     public Nullable<int> BaseColor
  10:     {
  11:         get { return _baseColor; }
  12:         set
  13:         {
  14:             _baseColor = value;
  15:             OnPropertyChanged("BaseColor");
  16:         }
  17:     }
  18:     #endregion //BaseColor
  19:  
  20:     #region Description
  21:     private string _description;
  22:  
  23:     public string Description
  24:     {
  25:         get { return _description; }
  26:         set
  27:         {
  28:             _description = value;
  29:             OnPropertyChanged("Description");
  30:  
  31:         }
  32:     }
  33:     #endregion //Description
  34:  
  35:     #region Id
  36:     private string _id;
  37:  
  38:     public string Id
  39:     {
  40:         get { return _id; }
  41:         set
  42:         {
  43:             _id = value;
  44:             OnPropertyChanged("Id");
  45:         }
  46:  
  47:     }
  48:     #endregion //Id
  49:  
  50:     #region IsVisible
  51:     private string _isVisible;
  52:  
  53:     public string IsVisible
  54:     {
  55:         get { return _isVisible; }
  56:         set
  57:         {
  58:             _isVisible = value;
  59:             OnPropertyChanged("IsVisible");
  60:         }
  61:     }
  62:     #endregion //IsVisible
  63:  
  64:     #region Name
  65:     private string _name;
  66:  
  67:     public string Name
  68:     {
  69:         get { return _name; }
  70:         set
  71:         {
  72:             _name = value;
  73:             OnPropertyChanged("Name");
  74:         }
  75:     }
  76:     #endregion //Name
  77:  
  78:     #region OwningResourceId
  79:     private string _owningResourceId;
  80:  
  81:     public string OwningResourceId
  82:     {
  83:         get { return _owningResourceId; }
  84:         set
  85:         {
  86:             _owningResourceId = value;
  87:             OnPropertyChanged("OwningResourceId");
  88:         }
  89:     }
  90:     #endregion //OwningResourceId
  91:  
  92:     #region UnmappedProperties
  93:     private string _unmappedProperties;
  94:  
  95:     public string UnmappedProperties
  96:     {
  97:         get { return _unmappedProperties; }
  98:         set { _unmappedProperties = value; }
  99:     }
 100:     #endregion //UnmappedProperties 
 101:  
 102:     #endregion //Proeprties
 103:  
 104: }

 

AppointmentInfo class:

   1: public class AppointmentInfo : BaseViewModel
   2: {
   3:  
   4:     #region Properties
   5:  
   6:     #region Description
   7:     /// <summary>
   8:     /// local variable _description
   9:     /// </summary>
  10:     private string _description;
  11:  
  12:     /// <summary>
  13:     /// Identifies the Description property.
  14:     /// </summary>        
  15:     public string Description
  16:     {
  17:         get { return _description; }
  18:         set
  19:         {
  20:             _description = value;
  21:             OnPropertyChanged("Description");
  22:         }
  23:     }
  24:     #endregion  //Description
  25:  
  26:     #region End
  27:  
  28:     /// <summary>
  29:     /// local variable _end
  30:     /// </summary>
  31:     private DateTime _end; // = DateTime.Now;
  32:  
  33:     /// <summary>
  34:     /// Identifies the End property.
  35:     /// </summary>        
  36:     public DateTime End
  37:     {
  38:         get { return _end; }
  39:         set
  40:         {
  41:             _end = value;
  42:             OnPropertyChanged("End");
  43:         }
  44:     }
  45:     #endregion  //End
  46:  
  47:     #region EndTimeZoneId
  48:     /// <summary>
  49:     /// local variable _endTimeZoneId
  50:     /// </summary>
  51:     private string _endTimeZoneId;
  52:  
  53:     /// <summary>
  54:     /// Identifies the EndTimeZoneId property.
  55:     /// </summary>        
  56:     public string EndTimeZoneId
  57:     {
  58:         get { return _endTimeZoneId; }
  59:         set
  60:         {
  61:             _endTimeZoneId = value;
  62:             OnPropertyChanged("EndTimeZoneId");
  63:         }
  64:     }
  65:     #endregion  //EndTimeZoneId
  66:  
  67:     #region Id
  68:     /// <summary>
  69:     /// local variable _id
  70:     /// </summary>
  71:     private string _id;
  72:  
  73:     /// <summary>
  74:     /// Identifies the Id property.
  75:     /// </summary>        
  76:     public string Id
  77:     {
  78:         get { return _id; }
  79:         set
  80:         {
  81:             _id = value;
  82:             OnPropertyChanged("Id");
  83:         }
  84:     }
  85:     #endregion  //Id
  86:  
  87:     #region IsLocked
  88:     /// <summary>
  89:     /// local variable _myVar
  90:     /// </summary>
  91:     private Nullable<bool> _isLocked = true;
  92:  
  93:     /// <summary>
  94:     /// Identifies the IsLocked property.
  95:     /// </summary>        
  96:     public Nullable<bool> IsLocked
  97:     {
  98:         get { return _isLocked; }
  99:         set
 100:         {
 101:             _isLocked = value;
 102:             OnPropertyChanged("IsLocked");
 103:         }
 104:     }
 105:     #endregion  //IsLocked
 106:  
 107:     #region IsOccurrenceDeleted
 108:     /// <summary>
 109:     /// local variable _isOccurrenceDeleted
 110:     /// </summary>
 111:     private Nullable<bool> _isOccurrenceDeleted;
 112:  
 113:     /// <summary>
 114:     /// Identifies the IsOccurrenceDeleted property.
 115:     /// </summary>        
 116:     public Nullable<bool> IsOccurrenceDeleted
 117:     {
 118:         get { return _isOccurrenceDeleted; }
 119:         set
 120:         {
 121:             _isOccurrenceDeleted = value;
 122:             OnPropertyChanged("IsOccurrenceDeleted");
 123:         }
 124:     }
 125:     #endregion  //IsOccurrenceDeleted
 126:  
 127:     #region IsTimeZoneNeutral
 128:     /// <summary>
 129:     /// local variable _isTimeZoneNeutral
 130:     /// </summary>
 131:     private bool _isTimeZoneNeutral;
 132:  
 133:     /// <summary>
 134:     /// Identifies the IsTimeZoneNeutral property.
 135:     /// </summary>        
 136:     public bool IsTimeZoneNeutral
 137:     {
 138:         get { return _isTimeZoneNeutral; }
 139:         set
 140:         {
 141:             _isTimeZoneNeutral = value;
 142:             OnPropertyChanged("IsTimeZoneNeutral");
 143:         }
 144:     }
 145:     #endregion  //IsTimeZoneNeutral
 146:  
 147:     #region IsVisible
 148:     /// <summary>
 149:     /// local variable _isVisible
 150:     /// </summary>
 151:     private Nullable<bool> _isVisible;
 152:  
 153:     /// <summary>
 154:     /// Identifies the IsVisible property.
 155:     /// </summary>        
 156:     public Nullable<bool> IsVisible
 157:     {
 158:         get { return _isVisible; }
 159:         set
 160:         {
 161:             _isVisible = value;
 162:             OnPropertyChanged("IsVisible");
 163:         }
 164:     }
 165:     #endregion  //IsVisible
 166:  
 167:     #region Location
 168:     /// <summary>
 169:     /// local variable _location
 170:     /// </summary>
 171:     private string _location;
 172:  
 173:     /// <summary>
 174:     /// Identifies the Location property.
 175:     /// </summary>        
 176:     public string Location
 177:     {
 178:         get { return _location; }
 179:         set
 180:         {
 181:             _location = value;
 182:             OnPropertyChanged("Location");
 183:         }
 184:     }
 185:     #endregion  //Location
 186:  
 187:     #region MaxOccurrenceDateTime
 188:     /// <summary>
 189:     /// local variable _mxOccurrenceDateTime
 190:     /// </summary>
 191:     private Nullable<DateTime> _mxOccurrenceDateTime;
 192:  
 193:     /// <summary>
 194:     /// Identifies the MaxOccurrenceDateTime property.
 195:     /// </summary>        
 196:     public Nullable<DateTime> MaxOccurrenceDateTime
 197:     {
 198:         get { return _mxOccurrenceDateTime; }
 199:         set
 200:         {
 201:             _mxOccurrenceDateTime = value;
 202:             OnPropertyChanged("MaxOccurrenceDateTime");
 203:         }
 204:     }
 205:     #endregion  //MaxOccurrenceDateTime
 206:  
 207:     #region OriginalOccurrenceEnd
 208:  
 209:     /// <summary>
 210:     /// local variable _originalOccurrenceEnd
 211:     /// </summary>
 212:     private DateTime _originalOccurrenceEnd; // = DateTime.Now;
 213:  
 214:     /// <summary>
 215:     /// Identifies the OriginalOccurrenceEnd property.
 216:     /// </summary>        
 217:     public DateTime OriginalOccurrenceEnd
 218:     {
 219:         get { return _originalOccurrenceEnd; }
 220:         set
 221:         {
 222:             _originalOccurrenceEnd = value;
 223:             OnPropertyChanged("OriginalOccurrenceEnd");
 224:         }
 225:     }
 226:     #endregion  //OriginalOccurrenceEnd
 227:  
 228:     #region OriginalOccurrenceStart
 229:  
 230:     /// <summary>
 231:     /// local variable _originalOccurrenceStart
 232:     /// </summary>
 233:     private DateTime _originalOccurrenceStart; // = DateTime.Now;
 234:  
 235:     /// <summary>
 236:     /// Identifies the OriginalOccurrenceStart property.
 237:     /// </summary>        
 238:     public DateTime OriginalOccurrenceStart
 239:     {
 240:         get { return _originalOccurrenceStart; }
 241:         set
 242:         {
 243:             _originalOccurrenceStart = value;
 244:             OnPropertyChanged("OriginalOccurrenceStart");
 245:         }
 246:     }
 247:     #endregion  //OriginalOccurrenceStart
 248:  
 249:     #region OwningCalendarId
 250:     /// <summary>
 251:     /// local variable _owningCalendarId
 252:     /// </summary>
 253:     private string _owningCalendarId;
 254:  
 255:     /// <summary>
 256:     /// Identifies the OwningCalendarId property.
 257:     /// </summary>        
 258:     public string OwningCalendarId
 259:     {
 260:         get { return _owningCalendarId; }
 261:         set
 262:         {
 263:             _owningCalendarId = value;
 264:             OnPropertyChanged("OwningCalendarId");
 265:         }
 266:     }
 267:     #endregion  //OwningCalendarId
 268:  
 269:     #region OwningResourceId
 270:     /// <summary>
 271:     /// local variable _owningResourceId
 272:     /// </summary>
 273:     private string _owningResourceId;
 274:  
 275:     /// <summary>
 276:     /// Identifies the OwningResourceId property.
 277:     /// </summary>        
 278:     public string OwningResourceId
 279:     {
 280:         get { return _owningResourceId; }
 281:         set
 282:         {
 283:             _owningResourceId = value;
 284:             OnPropertyChanged("OwningResourceId");
 285:         }
 286:     }
 287:     #endregion  //OwningResourceId
 288:  
 289:     #region Recurrence
 290:     /// <summary>
 291:     /// local variable _recurrence
 292:     /// </summary>
 293:     private string _recurrence;
 294:  
 295:     /// <summary>
 296:     /// Identifies the Recurrence property.
 297:     /// </summary>        
 298:     public string Recurrence
 299:     {
 300:         get { return _recurrence; }
 301:         set
 302:         {
 303:             _recurrence = value;
 304:             OnPropertyChanged("Recurrence");
 305:         }
 306:     }
 307:     #endregion  //Recurrence
 308:  
 309:     #region RecurrenceVersion
 310:     /// <summary>
 311:     /// local variable _recurrenceVersion
 312:     /// </summary>
 313:     private Nullable<int> _recurrenceVersion;
 314:  
 315:     /// <summary>
 316:     /// Identifies the RecurrenceVersion property.
 317:     /// </summary>        
 318:     public Nullable<int> RecurrenceVersion
 319:     {
 320:         get { return _recurrenceVersion; }
 321:         set
 322:         {
 323:             _recurrenceVersion = value;
 324:             OnPropertyChanged("RecurrenceVersion");
 325:         }
 326:     }
 327:     #endregion  //RecurrenceVersion
 328:  
 329:     #region Reminder
 330:     /// <summary>
 331:     /// local variable _reminder
 332:     /// </summary>
 333:     private string _reminder;
 334:  
 335:     /// <summary>
 336:     /// Identifies the Reminder property.
 337:     /// </summary>        
 338:     public string Reminder
 339:     {
 340:         get { return _reminder; }
 341:         set
 342:         {
 343:             _reminder = value;
 344:             OnPropertyChanged("Reminder");
 345:         }
 346:     }
 347:     #endregion  //Reminder
 348:  
 349:     #region ReminderEnabled
 350:     /// <summary>
 351:     /// local variable _reminderEnabled
 352:     /// </summary>
 353:     private Nullable<bool> _reminderEnabled;
 354:  
 355:     /// <summary>
 356:     /// Identifies the ReminderEnabled property.
 357:     /// </summary>        
 358:     public Nullable<bool> ReminderEnabled
 359:     {
 360:         get { return _reminderEnabled; }
 361:         set
 362:         {
 363:             _reminderEnabled = value;
 364:             OnPropertyChanged("ReminderEnabled");
 365:         }
 366:     }
 367:     #endregion  //ReminderEnabled
 368:  
 369:     #region ReminderInterval
 370:     /// <summary>
 371:     /// local variable _ReminderInterval
 372:     /// </summary>
 373:     private TimeSpan _reminderInterval;
 374:  
 375:     /// <summary>
 376:     /// Identifies the ReminderInterval property.
 377:     /// </summary>        
 378:     public TimeSpan ReminderInterval
 379:     {
 380:         get { return _reminderInterval; }
 381:         set
 382:         {
 383:             _reminderInterval = value;
 384:             OnPropertyChanged("ReminderInterval");
 385:         }
 386:     }
 387:     #endregion  //ReminderInterval
 388:  
 389:     #region RootActivityId
 390:     /// <summary>
 391:     /// local variable _rootActivityId
 392:     /// </summary>
 393:     private string _rootActivityId;
 394:  
 395:     /// <summary>
 396:     /// Identifies the RootActivityId property.
 397:     /// </summary>        
 398:     public string RootActivityId
 399:     {
 400:         get { return _rootActivityId; }
 401:         set
 402:         {
 403:             _rootActivityId = value;
 404:             OnPropertyChanged("RootActivityId");
 405:         }
 406:     }
 407:     #endregion  //RootActivityId
 408:  
 409:     #region Start
 410:  
 411:     /// <summary>
 412:     /// local variable _start
 413:     /// </summary>
 414:     private DateTime _start; // = DateTime.Now;
 415:  
 416:     /// <summary>
 417:     /// Identifies the Start property.
 418:     /// </summary>        
 419:     public DateTime Start
 420:     {
 421:         get { return _start; }
 422:         set
 423:         {
 424:             _start = value;
 425:             OnPropertyChanged("Start");
 426:         }
 427:     }
 428:     #endregion  //Start
 429:  
 430:     #region StartTimeZoneId
 431:     /// <summary>
 432:     /// local variable _startTimeZoneId
 433:     /// </summary>
 434:     private string _startTimeZoneId;
 435:  
 436:     /// <summary>
 437:     /// Identifies the StartTimeZoneId property.
 438:     /// </summary>        
 439:     public string StartTimeZoneId
 440:     {
 441:         get { return _startTimeZoneId; }
 442:         set
 443:         {
 444:             _startTimeZoneId = value;
 445:             OnPropertyChanged("StartTimeZoneId");
 446:         }
 447:     }
 448:     #endregion  //StartTimeZoneId
 449:  
 450:     #region Subject
 451:     /// <summary>
 452:     /// local variable _myVar
 453:     /// </summary>
 454:     private string _subject;
 455:  
 456:     /// <summary>
 457:     /// Identifies the Subject property.
 458:     /// </summary>        
 459:     public string Subject
 460:     {
 461:         get { return _subject; }
 462:         set
 463:         {
 464:             _subject = value;
 465:             OnPropertyChanged("Subject");
 466:         }
 467:     }
 468:     #endregion  //Subject
 469:  
 470:     #region UnmappedProperties
 471:     /// <summary>
 472:     /// local variable _unmappedProperties
 473:     /// </summary>
 474:     private string _unmappedProperties;
 475:  
 476:     /// <summary>
 477:     /// Identifies the UnmappedProperties property.
 478:     /// </summary>        
 479:     public string UnmappedProperties
 480:     {
 481:         get { return _unmappedProperties; }
 482:         set
 483:         {
 484:             _unmappedProperties = value;
 485:             OnPropertyChanged("UnmappedProperties");
 486:         }
 487:     }
 488:     #endregion  //UnmappedProperties
 489:  
 490:     #region VariantProperties
 491:     /// <summary>
 492:     /// local variable _variantProperties
 493:     /// </summary>
 494:     private Nullable<long> _variantProperties;
 495:  
 496:     /// <summary>
 497:     /// Identifies the VariantProperties property.
 498:     /// </summary>        
 499:     public Nullable<long> VariantProperties
 500:     {
 501:         get { return _variantProperties; }
 502:         set
 503:         {
 504:             _variantProperties = value;
 505:             OnPropertyChanged("VariantProperties");
 506:         }
 507:     }
 508:     #endregion  //VariantProperties 
 509:  
 510:     #endregion //Properties
 511:  
 512: }

 

Create a class, named ScheduleViewModel, that contains a collections that XamSchedule suite needs: data  for resources (usually users) , resource calendars (calendars) and appointments. It is also possible to have data for tasks and journals (notes), that are not included in this sample.

 

   1: public class ScheduleViewModel : BaseViewModel
   2:     {
   3:  
   4:         #region Construtors
   5:         public ScheduleViewModel()
   6:         {
   7:         }
   8:  
   9:         public ScheduleViewModel(string currentUserId, string currentUserName, string currentUserCalendarId)
  10:         {
  11:             Resources.Add(new ResourceInfo
  12:             {
  13:                 Id = currentUserId,
  14:                 Name = currentUserName
  15:  
  16:             });
  17:  
  18:             ResourceCalendars.Add(new ResourceCalendarInfo
  19:             {
  20:                 Id = currentUserCalendarId,
  21:                 OwningResourceId = currentUserId
  22:             });
  23:  
  24:             this.CurrentResourceCalendar = this.ResourceCalendars[0];
  25:  
  26:         }
  27:         #endregion //Construtors
  28:  
  29:         #region Properties
  30:  
  31:         #region Appointments
  32:         private ObservableCollection<AppointmentInfo> _appointments = new ObservableCollection<AppointmentInfo>();
  33:         public ObservableCollection<AppointmentInfo> Appointments
  34:         {
  35:             get { return _appointments; }
  36:             set
  37:             {
  38:                 _appointments = value;
  39:                 OnPropertyChanged("Appointments");
  40:             }
  41:         }
  42:         #endregion //Appointments
  43:  
  44:         #region CalendarDisplayMode
  45:         /// <summary>
  46:         /// local variable _CalendarDisplayMode 
  47:         /// </summary>
  48:         private CalendarDisplayMode _calendarDisplayMode = CalendarDisplayMode.Separate;
  49:  
  50:         /// <summary>
  51:         /// Identifies the CalendarDisplayMode  property.
  52:         /// </summary>        
  53:         public CalendarDisplayMode CalendarDisplayMode
  54:         {
  55:             get { return _calendarDisplayMode; }
  56:             set
  57:             {
  58:                 _calendarDisplayMode = value;
  59:                 OnPropertyChanged("CalendarDisplayMode ");
  60:             }
  61:         }
  62:         #endregion  //CalendarDisplayMode
  63:  
  64:         #region CurrentResourceCalendar
  65:         private ResourceCalendarInfo _currentResourceCalendar = new ResourceCalendarInfo();
  66:         [System.Xml.Serialization.XmlIgnoreAttribute]
  67:         public ResourceCalendarInfo CurrentResourceCalendar
  68:         {
  69:             get { return _currentResourceCalendar; }
  70:             set
  71:             {
  72:                 _currentResourceCalendar = value;
  73:                 OnPropertyChanged("CurrentResourceCalendar");
  74:             }
  75:         }
  76:         #endregion //CurrentResourceCalendar
  77:  
  78:         #region Resources
  79:         private ObservableCollection<ResourceInfo> _resources = new ObservableCollection<ResourceInfo>();
  80:         public ObservableCollection<ResourceInfo> Resources
  81:         {
  82:             get { return _resources; }
  83:             set
  84:             {
  85:                 _resources = value;
  86:                 OnPropertyChanged("Resources");
  87:             }
  88:         }
  89:         #endregion //Resources
  90:  
  91:         #region ResourceCalendars
  92:         private ObservableCollection<ResourceCalendarInfo> _resourceCalendars = new ObservableCollection<ResourceCalendarInfo>();
  93:         public ObservableCollection<ResourceCalendarInfo> ResourceCalendars
  94:         {
  95:             get { return _resourceCalendars; }
  96:             set
  97:             {
  98:                 _resourceCalendars = value;
  99:                 OnPropertyChanged("ResourceCalendars");
 100:             }
 101:         }
 102:         #endregion //ResourceCalendars 
 103:  
 104:         #endregion //Properties
 105:  
 106:     }

 

Add a ListScheduleDataConnector and Set the Mapping Fields.

Add a ListScheduleDataConnector in the MainPage.xaml

   1: <ig:ListScheduleDataConnector HorizontalAlignment="Left" Name="listScheduleDataConnector1" VerticalAlignment="Top"                
   2:                ResourceItemsSource="{Binding Resources, Mode=TwoWay}" Loaded="ListScheduleDataConnector1Loaded" 
   3:                ResourceCalendarItemsSource="{Binding ResourceCalendars, Mode=TwoWay}"  
   4:                 AppointmentItemsSource="{Binding Appointments, Mode=TwoWay}">
   5:             <ig:ListScheduleDataConnector.ResourcePropertyMappings>
   6:                 <ig:ResourcePropertyMappingCollection UseDefaultMappings="True"/>
   7:             </ig:ListScheduleDataConnector.ResourcePropertyMappings>
   8:             <ig:ListScheduleDataConnector.ResourceCalendarPropertyMappings>
   9:                 <ig:ResourceCalendarPropertyMappingCollection UseDefaultMappings="True"/>
  10:             </ig:ListScheduleDataConnector.ResourceCalendarPropertyMappings>
  11:             <ig:ListScheduleDataConnector.AppointmentPropertyMappings>
  12:                 <ig:AppointmentPropertyMappingCollection UseDefaultMappings="True"/>
  13:             </ig:ListScheduleDataConnector.AppointmentPropertyMappings>
  14:         </ig:ListScheduleDataConnector>

 

ResourcePropertyMappings, ResourceCaendarPropertyMappings and AppointmentPropertyMappings are used to map of properties between data source objects and xamSchedule objects. In the sample are used default mappings because of equal names of the properties in data source objects and XamSchedule objects.

Add a XamScheduleDataManager.

Add a XamScheduleDataManager in the XAML and set created ListScheduleDataConnector instance like a DataConnector :

   1: <ig:XamScheduleDataManager HorizontalAlignment="Left" Name="xamScheduleDataManager1"  CurrentUserId="currentUser"
   2:      VerticalAlignment="Top" DataConnector="{Binding ElementName=listScheduleDataConnector1}" >
   3:     <ig:XamScheduleDataManager.Settings>
   4:         <ig:ScheduleSettings>
   5:             <ig:ScheduleSettings.AppointmentSettings>
   6:                 <ig:AppointmentSettings AllowEdit="False"  AllowDragging="No" AllowResizing="No"/>
   7:             </ig:ScheduleSettings.AppointmentSettings>
   8:         </ig:ScheduleSettings>
   9:     </ig:XamScheduleDataManager.Settings>
  10: </ig:XamScheduleDataManager>

It is possible to add in the Settings property settings for activities behaviors (AppointmentSettings in this sample).  There is prevented editing of the settings.

 

Add UI Components from Schedule Suite: XamDayView, XamScheduleView, XamMonthView.

To propose a different views in the application add XamDayView, XamScheduleView and XamMonthView components:

   1: <ig:XamDayView HorizontalAlignment="Stretch"  Name="xamDayView1" VerticalAlignment="Stretch" 
   2:                             DataManager="{Binding ElementName=xamScheduleDataManager1}" MultiDayActivityAreaVisibility="Visible" />
   3:         <ig:XamScheduleView HorizontalAlignment="Stretch" Name="xamScheduleView1" VerticalAlignment="Stretch" 
   4:                             DataManager="{Binding ElementName=xamScheduleDataManager1}" Visibility="Collapsed" />
   5:         <ig:XamMonthView HorizontalAlignment="Stretch"  Name="xamMonthView1" VerticalAlignment="Stretch" 
   6:                             DataManager="{Binding ElementName=xamScheduleDataManager1}" Visibility="Collapsed" />
   7:         <ig:XamOutlookBar Grid.Column="1" HorizontalAlignment="Stretch" Name="xamOutlookBar1" VerticalAlignment="Stretch">

 

In each moment only one of three views will be visible: XamDayView, XamScheduleView view or XamMonthView.
To be possible to switch between different view there is a list box added with a logic to change the view when selection is changed:

   1: <ListBox x:Name="ListScheduleViews" Margin="0 0 0 -2"   SelectionMode="Single"  SelectionChanged="ListScheduleViews_SelectionChanged">
   2:     <ListBox.ItemsPanel>
   3:         <ItemsPanelTemplate>                                       
   4:             <StackPanel Orientation="Vertical" Margin="0" Width="150" />
   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>

 

C# code for changing the visibility of the views.

   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 a Multi Calendar Support.

Sometimes one resource needs to use different calendars for different purposes.
To display more  calendars for one resource you need to add these calendars in the same calendar group.

Each time when CalendarResource is added by default it is in separate group:

ScheduleViewModel scheduleViewModel;

…..

ResourceCalendarInfo calendar = new ResourceCalendarInfo();

_scheduleViewModel.ResourceCalendars.Add(calendar);

This expression is adding a calendar with w new group.

To add more calendars in the same group when add it there is an appropriate sample:

   1: #region InitResourceCalendar
   2: private void InitResourceCalendar(ResourceCalendarInfo calendar)
   3: {
   4:  
   5:         var resource = xamScheduleDataManager1.ResourceItems.GetResourceFromId(this._scheduleViewModel.Resources[0].Id);
   6:  
   7:         if (resource == null)
   8:         {
   9:             return;
  10:         }
  11:  
  12:         ResourceCalendar calendar2 = resource.Calendars.First(c => c.Id == calendar.Id);
  13:  
  14:         CalendarGroup groupWithCalendarAdded =
  15:             xamScheduleDataManager1.CalendarGroups.FirstOrDefault(cg => cg.Calendars.Contains(calendar2));
  16:         if (groupWithCalendarAdded != null)
  17:         {
  18:             groupWithCalendarAdded.Calendars.Remove(calendar2);
  19:             if (groupWithCalendarAdded.Calendars.Count == 0)
  20:                 xamScheduleDataManager1.CalendarGroups.Remove(groupWithCalendarAdded);
  21:         }
  22:  
  23:         CalendarGroup calGroup;
  24:         if (xamScheduleDataManager1.CalendarGroups.Count > 0)
  25:         {
  26:             int index = 0;
  27:             calGroup = xamScheduleDataManager1.CalendarGroups[index];
  28:             calGroup.Calendars.Add(calendar2);
  29:         }
  30:         else
  31:         {
  32:             calGroup = new CalendarGroup();
  33:             calGroup.Calendars.Add(calendar2);
  34:             xamScheduleDataManager1.CalendarGroups.Add(calGroup);
  35:         }
  36:  
  37: }
  38: #endregion //InitResourceCalendar

 

Implement Runtime Support for Calendar Display Mode.

When a resource has more calendars different calendars could be represented together in different ways:
Separate, Overlay or Merged.

You could learn more about CalendarDisplayMode property for XamSchedule views there.

There is a sample how to add a ComboBox with all values for enum CalendarDisplayMode and when a selection is changed it changes the CalendarDisplayMode  property value for each of three views:

   1: <ComboBox x:Name="cmbCalendarDisplayMode" Margin="0,10,0,0" Width="140" HorizontalAlignment="Stretch"
   2:                             ItemsSource="{Binding CalendarDisplayMode, Mode=TwoWay, Converter={StaticResource enumConverter}}" 
   3:                             SelectedItem="{Binding CalendarDisplayMode, Mode=TwoWay}" Foreground="Black" SelectionChanged="CmbCalendarDisplayModeSelectionChanged"/>

 

Here is a code used to change CalendarDisplayMode property in all views.

   1: #region CmbCalendarDisplayModeSelectionChanged
   2: private void CmbCalendarDisplayModeSelectionChanged(object sender, SelectionChangedEventArgs e)
   3: {
   4:     if (e.AddedItems.Count < 1)
   5:     {
   6:         return;
   7:     }
   8:  
   9:     CalendarDisplayMode cmode = (CalendarDisplayMode)e.AddedItems[0];
  10:  
  11:     this.xamDayView1.CalendarDisplayMode = cmode;
  12:     this.xamScheduleView1.CalendarDisplayMode = cmode;
  13:     this.xamMonthView1.CalendarDisplayMode = cmode;
  14: }
  15: #endregion //CmbCalendarDisplayModeSelectionChanged

 

Implement persistence of the current XamSchedule Settings.

Sometimes it is convenient to persist part of the Schedule settings and data locally because of connection issues or if you need to make some changes before submit a data on the server.

The code below demonstrate how to save a data to the Isolated Storage and load it in the application.

 

   1:  
   2:         #region BtnLoadData_Click
   3:         private void BtnLoadData_Click(object sender, RoutedEventArgs e)
   4:         {
   5:  
   6:             XmlSerializer xs = new XmlSerializer(typeof(ScheduleViewModel));
   7:  
   8:             Stream str = new MemoryStream(ReadDataFromStore(IsoFile));
   9:             using (StreamReader rd = new StreamReader(str))
  10:             {
  11:                 ScheduleViewModel favourites = xs.Deserialize(rd) as ScheduleViewModel;
  12:                 if (favourites != null)
  13:                 {
  14:                     this._scheduleViewModel.Appointments.Clear();
  15:                     this._scheduleViewModel.ResourceCalendars.Clear();
  16:  
  17:                     foreach (ResourceCalendarInfo calInfo in favourites.ResourceCalendars)
  18:                     {
  19:                         this._scheduleViewModel.ResourceCalendars.Add(calInfo);
  20:                         this.InitResourceCalendar(calInfo);
  21:                     }
  22:  
  23:                     foreach (AppointmentInfo app in favourites.Appointments)
  24:                     {
  25:                         this._scheduleViewModel.Appointments.Add(app);
  26:                     }
  27:                 }
  28:             }
  29:         }
  30:         #endregion //BtnLoadData_Click
  31:         
  32:         #region BtnSaveData_Click
  33:         private void BtnSaveData_Click(object sender, RoutedEventArgs e)
  34:         {
  35:             XmlSerializer xs = new XmlSerializer(typeof(ScheduleViewModel));
  36:             MemoryStream str = new MemoryStream();
  37:             StreamWriter sr = new StreamWriter(str);
  38:             xs.Serialize(sr, this._scheduleViewModel);
  39:             WriteDataToStore(str.ToArray(), IsoFile);
  40:         }
  41:         #endregion //BtnSaveData_Click        
  42:  
  43:  
  44:         #region ReadDataFromStore
  45:         //Reads a file from the Isolated Storage, specified by name
  46:         private static byte[] ReadDataFromStore(string fileName)
  47:         {
  48:             using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  49:             {
  50:                 IsolatedStorageFileStream fileStream;
  51:                 fileStream = store.OpenFile(fileName, FileMode.Open);
  52:                 byte[] b = new byte[fileStream.Length];
  53:                 fileStream.Read(b, 0, (int)fileStream.Length);
  54:                 fileStream.Close();
  55:                 return b;
  56:             }
  57:         }
  58:         #endregion //ReadDataFromStore
  59:         
  60:  
  61:        #region WriteDataToStore
  62:         // Writes a file to an Isolated IStrorage, specified via its name 
  63:         // and content like a byte array
  64:         private static void WriteDataToStore(byte[] data, string fileName)
  65:         {
  66:             if (data == null || data.Length == 0)
  67:                 return;
  68:             using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  69:             {
  70:                 CleanStorage(store);
  71:  
  72:                 IsolatedStorageFileStream fileStream = store.CreateFile(fileName);
  73:                 fileStream.Write(data, 0, data.Length);
  74:                 fileStream.Close();
  75:  
  76:             }
  77:         }


 

Handle TimeZone Options.

Proper support for time zones is essential in any robust scheduling system.

Providing time-zone information:

In order for time-zone conversions to be made accurately, the scheduling controls must have access to information about every time zone, including each time zone’s base UTC offset as well as its set of rules that define when daylight savings time starts and ends in each year.

The WPF framework provides this information for all time zones through its TimeZoneInfo class. In Silverlight the TimeZoneInfo class exists in the framework but it only exposes the information for the ‘local’ and ‘UTC’ time zones.

About TimeZone Support in xamSchedule you could find more information here:

In many regions there are same Daylight Saving Time. Therefore since the Silverlight framework doesn’t expose enough information to tell us which time zone we are in we have to prompt the user. This is generally not a problem in WPF since that framework exposes the local time zone id.  the Silverlight Schedule there is no way to get it from Windows. In many time zones this is not a problem because there is only one time zone with the exact same DST conversion rules so we know definitively which one to use and therefore we do not prompt the user. However, even in those Time zones if the user unchecked the “Automatically adjust clock for Daylight Savings Time” check box we would have to display the time zone selection dialog.

You could see the dialog in these cases when application has started.

To prevent this you could set to DataConnector in TimeZoneInfoProviderResolved.LocalTimeZoneId a valid time zone:

   1: #region ListScheduleDataConnector1Loaded
   2: private void ListScheduleDataConnector1Loaded(object sender, RoutedEventArgs e)
   3: {
   4:  
   5:     listScheduleDataConnector1.TimeZoneInfoProviderResolved.LocalTimeZoneId = "Jordan Standard Time";
   6:  
   7: }
   8: #endregion //ListScheduleDataConnector1Loaded

 

Test  the same application:

Start the application:
TimeZone is pre set and now is no need to select it from dialog window.
Default view is XamDayView instance.

In the XamOutlookBar right in the screen select group “Calendars” and click over “Create new..”
Dialog Window has appeared to set a new ResourceCalendar.
After confirmation the new ResourceCalendar instance has added  on the screen. CalendarDisplayMode mode is “Separate”.

Click on the “Maintenance” group.

Expand the “Schedule View” expander.

Select “Schedule View” from the list:
Now XamScheduleView view is visible, XamDayView instance – collapsed.

Select “Month View” from the list.

Change the CalendarDisplayMode :

From “Calendar Display Mode” ComboBox change the option to “Overlay”.
Calendar are overlapped (headers are like a different sheets to propose selection).

From “Calendar Display Mode” ComboBox change the option to “Merged”.
Calendars has merged.

Add an appointment via double click over XamDayView component.

Change the current calendar via selection from UI and add a second appointment.

Change the CalendarDisplayMode to “Merged”.Save the data locally via “Save Data” button and reload the application

Select “Load Data” to load the saved calendars and appointments.

You could download the sample application XamScheduleDemo.zip: