Telerik blogs

Have you ever had to organize a complex schedule for an event, scheduling sessions and juggling resources? Using the RadScheduler control in an application makes this task a breeze. Simply configure a data source and visually arrange your schedule on the fly by adding, removing and editing sessions. RadScheduler comes out of the box with already implemented context menus and editor dialogs thus reducing development time and providing users with the familiar Outlook-style usability. RadScheduler also gives users the ability to drag and drop sessions into different timeslots, avoiding the use of the editor dialogs completely, all of this while automatically keeping your data up to date in memory.

Please join me as I demonstrate to you how to create a useful conference planner using the RadScheduler by binding it to business objects.

image

Setting up the project

The first thing we need to do is to create a new Project, create a RadControls Windows Forms Application and name it RadScheduler.

image

In the Project Configuration Wizard, select Telerik.WinControls and Telerik.WinControls.Scheduler (you’ll notice the Telerik.WinControls.GridView automatically selects, this is because the Scheduler has a dependency on it).

image

Defining the business objects

Once the project is created, it’s time to implement our business objects. One thing to note is that in order to notify the Scheduler of data changes, the objects that you will be binding to the Scheduler must implement the INotifyPropertyChanged event.  To ease the development of these objects, I created a base class from which my objects will inherit.  This class is implemented as follows:

using System;
using System.ComponentModel;
using System.Linq;
 
namespace RadScheduler
{
 public class BaseEntity : INotifyPropertyChanged
    {
 public event PropertyChangedEventHandler PropertyChanged;
 
 protected void RaisePropertyChanged(string propertyName)
        {
 if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

The next thing to do is to define what one of our resources will look like that we will be scheduling.  In this case, we will be scheduling rooms, each room will be defined as containing a technical track.  The implementation of a Room is as follows, please note that both of these fields are key fields that will be mapped to a scheduler data source:

using System;
using System.Linq;
 
namespace RadScheduler
{
 public class Room : BaseEntity
    {
 private int _roomNumber;
 private string _trackName;
 
 
 public int RoomNumber
        {
            get { return _roomNumber; }
            set { 
                _roomNumber = value;
                RaisePropertyChanged("RoomNumber");
            }
        }
 
 public string TrackName
        {
            get { return _trackName; }
            set { 
                _trackName = value;
                RaisePropertyChanged("TrackName");
            }
        }
 
    }
}

Now we need to define the structure for the presentations being scheduled at the conference.  The presentation will be handled like an appointment in Outlook.  It is given a start and end time, as well as the ability to be associated with a resource, in this case a room. In order to ease implementation, ensure the Id field is of type Guid. Find the Presentation class as follows:

using System;
using System.Linq;
using Telerik.WinControls.UI;
 
namespace RadScheduler
{
 public class Presentation : BaseEntity
    {
 private Guid _id;
 private string _title;
 private string _abstract;
 private DateTime _startTime;
 private DateTime _endTime;
 private int _roomNumber;
 
 public int RoomNumber
        {
            get
            {
 return this._roomNumber;
            }
            set
            {
 this._roomNumber = value;
                RaisePropertyChanged("RoomNumber");
            }
        }
 
 public EventId ResourceId
        {
            get
            {
 return new EventId(_roomNumber);
            }
            set
            {
 this._roomNumber = (int)value.KeyValue;
                RaisePropertyChanged("ResourceId");
            }
        }
 
 public Guid Id
        {
            get
            {
 return this._id;
            }
            set
            {
 this._id = value;
                RaisePropertyChanged("Id");
            }
        }
 
 public string Title
        {
            get
            {
 return this._title;
            }
            set
            {
 this._title = value;
                RaisePropertyChanged("Title");
            }
        }
 
 public string Abstract
        {
            get
            {
 return this._abstract;
            }
            set
            {
 this._abstract = value;
                RaisePropertyChanged("Abstract");
            }
        }
 
 public DateTime StartTime
        {
            get
            {
 return this._startTime;
            }
            set
            {
 this._startTime = value;
                RaisePropertyChanged("StartTime");
            }
        }
 
 public DateTime EndTime
        {
            get
            {
 return this._endTime;
            }
            set
            {
 this._endTime = value;
                RaisePropertyChanged("EndTime");
            }
        }
 
    }
}

Defining the data repository

In order to load and save the data for the schedule, we will be using a repository class. The repository class provides ObservableCollections for Rooms and Presentations to bind to the scheduler data source. In this implementation, JSON data is being used, as this file will be hosted on a web server for mobile clients to consume. Remember your data can come from anywhere, but for those curious types you can find more information on using JSON with Windows Forms from this previous blog post. Add a new class to your project named ConferenceRepository.cs and define it as follows:

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
 
namespace RadScheduler
{
 public class ConferenceRepository
    {
 private string _jsonPresentationsFileName = "presentations.json";
 private string _jsonResourceFileName = @"StarterData\resources.json";
 
 private ObservableCollection<Presentation> _presentations;
 private ObservableCollection<Room> _rooms;
 
 public ObservableCollection<Room> Rooms
        {
            get
            {
 return this._rooms;
            }
            set
            {
 this._rooms = value;
            }
        }
 
 public ObservableCollection<Presentation> Presentations
        {
            get
            {
 return this._presentations;
            }
            set
            {
 this._presentations = value;
            }
        }
 
 public ConferenceRepository()
        {
 if (File.Exists(_jsonPresentationsFileName))
            {
                Presentations = JsonConvert.DeserializeObject<ObservableCollection<Presentation>>(File.ReadAllText(_jsonPresentationsFileName));
            }
 else
            {
                Presentations = new ObservableCollection<Presentation>();
            }
 
 if (File.Exists(_jsonResourceFileName))
            {
                Rooms = JsonConvert.DeserializeObject<ObservableCollection<Room>>(File.ReadAllText(_jsonResourceFileName));
            }
 else
            {
                Rooms = new ObservableCollection<Room>();
            }
        }
 
 public void PersistRepository()
        {
 using (StreamWriter sw = new StreamWriter(_jsonPresentationsFileName, false))
            {
 //save the presentations
 string presentationJson = JsonConvert.SerializeObject(Presentations, Formatting.Indented);
                sw.Write(presentationJson);
                sw.Close();
            }
        }
    }
}

Building the user interface

Now we will start designing our user interface. Open the designer for Form1.cs, expand the form to give you more real-estate, and drag an instance of a RadButton to the design surface, dock this button to the top and set its text property to “Save Schedule”. Now drag an instance of RadScheduler to the design surface, and set its dock to Fill. Your designer should now look something like this:

scheduler

Setting up the scheduler data source and mapping it to the business objects

Next we will begin setting up our data source. Drag an instance of a SchedulerBindingDataSource to the design surface, because this is a non-visual element, it will be displayed in the tray of the designer of the form. Click on the smart tag of the data source. Let’s setup the EventProvider properties first. Click on the drop down for the “Choose Data Source” and select Add Project Data Source. Select Object as Data Source Type:

image

Then navigate the object tree to select the ConferenceRepository class:

image

Click Finish and this will add a conferenceRepositoryBindingSource to the design surface next to your data source. Select the smart tag of your data source again and select the conferenceRepository as the data source for both Appointments and Resources, and assign the appropriate Properties from the ConferenceRepository as follows, then Save and Close:

image

Click on the Edit Appointment Mapping link to match up the appointment properties to our Presentation properties as follows:

image

Next click the Edit Resource Mapping link in the Smart Tag of the data source, set the following property mappings, then click Save and Close:

image

Next select the Smart Tag of the Scheduler control, and set the data source to schedulerBindingDataSource1.

Initializing the scheduler with our visual preferences and implementing user interaction

Now select the Form, and implement the Load event by double clicking on it in the properties pane to generate the method stub in code behind.  In the code view of the form, create a private field that will contain an instance of our repository.

private ConferenceRepository _repository;

Next implement the form Load event as follows:

private void Form1_Load(object sender, EventArgs e)
{
    _repository = new ConferenceRepository();
 
 //our conference is one day
    SchedulerDayView dayView = radScheduler1.GetDayView();
    dayView.DayCount = 1;
    dayView.StartDate = new DateTime(2013, 5, 17);
 
 //display the hours between 8am and 7pm in half hour chunks
    dayView.RulerStartScale = 8;
    dayView.RulerEndScale = 19;
    dayView.WorkTime = new TimeInterval(TimeSpan.FromHours(8), TimeSpan.FromHours(19));
    dayView.RangeFactor = ScaleRange.HalfHour;
 
 //set the binding source to our repository data
    conferenceRepositoryBindingSource.DataSource = _repository;
 
 //view the schedule grouped by resource
    radScheduler1.GroupType = GroupType.Resource;
}

Next return to the designer and double-click on the Save Schedule button, this will generate the click event in code behind, implement it as follows:

private void radButton1_Click(object sender, EventArgs e)
{
    _repository.PersistRepository();
    MessageBox.Show("Saved");
}

Now we are able to see our application in action – build and run the application. Add a few sessions using the context menu by clicking in a time slot of one of the conference tracks and selecting New Appointment. Once you’ve added a few, click the “Save Schedule” button and your schedule is saved using the ConferenceRepository and is preserved if you close and re-run the application once more.

image

Go ahead an move presentations between tracks (Resources) and times, notice how the data changes automatically in the user interface. Remember to save changes in order to persist modifications.

Summary

As you can see, when confronted with a scheduling requirement RadScheduler for WinForms can save you enormous amounts of development time as well as gives your users a familiar look and feel. You’ve also seen how straight forward it is to set up and configure. Please visit the RadScheduler overview page and documentation site for more information on the features and customizations of this rich control.

DOWNLOAD SOURCE

Download RadControls for WinForms by Telerik


About the Author

Carey Payette

Carey Payette is a Senior Software Engineer with Trillium Innovations (a Solliance partner), an ASPInsider, a Progress Ninja, a Microsoft Certified Trainer and a Microsoft Azure MVP. Her primary focus is cloud integration and deployment for the web, mobile, big data, AI, machine learning and IoT spaces. Always eager to learn, she regularly tinkers with various sensors, microcontrollers, programming languages and frameworks. Carey is also a wife and mom to three fabulous boys.

Comments

Comments are disabled in preview mode.