Log in to like this post! 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: Visual Studio 2010 Silverlight 4 Tools for Visual Studio 2010 Silverlight 4 Toolkit One of these distributions: NetAdvantage for Silverlight Line of Business 2010 Vol.3 NetAdvantage for .NET 2010 Vol.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: