Click here to Skip to main content
11,575,109 members (70,218 online)
Click here to Skip to main content

Creating an Outlook Calendar using WPF (Part 1)

, 21 Oct 2008 CPOL 166.8K 9.1K 217
Rate this:
Please Sign up or sign in to vote.
Recreate the Outlook Calendar using WPF.

Introduction

Microsoft Office is undoubtedly one of the best selling products in the world today! Thy always try and innovate… In this CodeProject article, I will try and recreate the Microsoft Outlook Calendar control using WPF.

All elements/controls in WPF are look-less! This reduces the need to create custom controls. A button is an element that supports clicking on it and then raising a Click event, but there is no restriction on how this button should look!

So, with my WPF think cap on, I tried to find a control that I could restyle to fit my calendar control… After trying out a few ideas, I decided to rather create a custom control.

Here are the basic elements of my custom Calendar control:

CalendarLedgerItem and CalendarLedger

Ledger.jpg

The ledger indicates the timeslot time.

CalendarTimeslotItem

Timeslot.jpg

Each day is divided into 30 minute slots (represented by CalendarTimeslotItem). CalendarTimeslotItem provides a very simple hover style to hint to the user that by clicking on the timeslot, you can add an appointment. The CalendarTimeslotItem also exposes (and raises) AddAppointmentEvent, which gets bubbled to the calendar (by clicking on the timeslot). CalendarTimeslotItem derives from ButtonBase.

public static readonly RoutedEvent AddAppointmentEvent = 
    EventManager.RegisterRoutedEvent("AddAppointment", RoutingStrategy.Bubble, 
    typeof(RoutedEventHandler), typeof(CalendarTimeslotItem));

CalendarAppointmentItem

AppointmentItem.jpg

CalendarAppointmentItem is a very generic container to show an appointment (similar to ListboxItem). I cheat a little by assuming that what every “item” CalendarDay binds to will have a StartTime and EndTime property!

<Setter Property="StartTime" Value="{Binding StartTime}" />
<Setter Property="EndTime" Value="{Binding EndTime}" />

[Note] I know this sucks a little… I will address this in part 2!

CalendarDay

The CalendarDay is the heart of our Outlook calendar. The CalendarDay derives from ItemsControl.

protected override DependencyObject GetContainerForItemOverride()
{            
    return new CalendarAppointmentItem();
}

protected override bool IsItemItsOwnContainerOverride(object item)
{
    return (item is CalendarAppointmentItem);
}

Each “item” added to the CalendarDay will implicitly have CalendarAppointmentItem as its container. This will all “magically” work, provided that the objects bound to the ItemsControl have the StartTime and EndTime properties!

TimeslotPanel

The last part we have to cover before we look at the calendar control is the TimeslotPanel. This custom layout panel will position each “item” in the CalendarDay control based on its start and end times!

<ItemsPanelTemplate>
    <local:TimeslotPanel />
</ItemsPanelTemplate>

Calendar

The Calendar adds an owner to the CalendarTimeslotItem.AddAppointmentEvent.

public static readonly RoutedEvent AddAppointmentEvent = 
    CalendarTimeslotItem.AddAppointmentEvent.AddOwner(typeof(CalendarDay));

Currently, the Calendar control is the only control that explicitly “knows” what the date is! It has a CurrentDate property.

public static readonly DependencyProperty CurrentDateProperty =
    DependencyProperty.Register("CurrentDate", typeof(DateTime), typeof(Calendar),
        new FrameworkPropertyMetadata((DateTime)DateTime.Now,
            new PropertyChangedCallback(OnCurrentDateChanged)));

The Calendar control also exposes two commands that can be used to change the current date:

public static readonly RoutedCommand NextDay = 
       new RoutedCommand("NextDay", typeof(Calendar));
public static readonly RoutedCommand PreviousDay = 
       new RoutedCommand("PreviousDay", typeof(Calendar));

Commands.jpg

These commands are self explanatory!

I have also created a very basic model:

Model.jpg

This model is used as the data source!

public static readonly DependencyProperty AppointmentsProperty =
    DependencyProperty.Register("Appointments", 
       typeof(IEnumerable<Appointment>), typeof(Calendar),
    new FrameworkPropertyMetadata(null, 
        new PropertyChangedCallback(Calendar.OnAppointmentsChanged)));

The only tricky part now is how to get the data bound to my Appointments property into my ItemsControl?

Introducing filters… Rob Conery’s MVC Storefront uses a similar approach!

public static class Filters 
{ 
    public static IEnumerable<Appointment> ByDate(
           thisIEnumerable<Appointment> appointments, DateTime date) 
    { 
        var app = froma inappointments 
                  wherea.StartTime.Date == date.Date 
                  selecta; 
        return app; 
    } 
}

This extension method allows me to “filter” my appointments by date (ignoring the time). Here is how it is currently used:

private void FilterAppointments()
{
    DateTime byDate = CurrentDate;
    CalendarDay day = this.GetTemplateChild("day") as CalendarDay;
    day.ItemsSource = Appointments.ByDate(byDate);

    TextBlock dayHeader = this.GetTemplateChild("dayHeader") as TextBlock;
    dayHeader.Text = byDate.DayOfWeek.ToString();
}

This approach allows me to relatively easily extend the calendar control to support a day or week view (by just adding multiple CalendarDay controls).

OutlookCalendar.jpg

And, that is it for part 1... If you found this article interesting, please vote for it, and also visit my blog!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

rudigrobler
South Africa South Africa
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 4 Pin
yangzhj28-Jul-13 15:06
memberyangzhj28-Jul-13 15:06 
GeneralMy vote of 5 Pin
Doudy_202021-Jun-13 5:06
memberDoudy_202021-Jun-13 5:06 
GeneralRe: My vote of 5 Pin
Member 110274843-Sep-14 0:34
memberMember 110274843-Sep-14 0:34 
GeneralRe: My vote of 5 Pin
Doudy_20203-Sep-14 1:26
memberDoudy_20203-Sep-14 1:26 
QuestionAdding datepicker Pin
Eng. Hudhud19-Jun-13 6:21
memberEng. Hudhud19-Jun-13 6:21 
AnswerRe: Adding datepicker Pin
Member 109927715-Aug-14 3:36
memberMember 109927715-Aug-14 3:36 
GeneralMy vote of 5 Pin
Mr.Golffy3-Jan-13 20:45
memberMr.Golffy3-Jan-13 20:45 
GeneralMy vote of 5 Pin
WikusOlivier23-Aug-12 5:56
memberWikusOlivier23-Aug-12 5:56 
GeneralMy vote of 5 Pin
monaShahid16-Oct-11 6:02
membermonaShahid16-Oct-11 6:02 
QuestionAdded appointments do not appear immediately Pin
adimas8-Sep-11 3:53
memberadimas8-Sep-11 3:53 
QuestionInstructions for changing timeslot to rooms Pin
koolkabin@live.com21-Jun-11 7:07
memberkoolkabin@live.com21-Jun-11 7:07 
QuestionRefresh Calendar Pin
serkan312331-May-11 1:15
memberserkan312331-May-11 1:15 
GeneralAdd into CalendarAppointmentItem more object (for ex. a TextBlock), but more also.... Pin
Dario Concilio4-Feb-11 22:55
memberDario Concilio4-Feb-11 22:55 
GeneralMy vote of 5 Pin
Dario Concilio4-Feb-11 22:52
memberDario Concilio4-Feb-11 22:52 
GeneralNeed same in Silverlight 3... Pin
Sumi .D8-Apr-10 1:59
memberSumi .D8-Apr-10 1:59 
GeneralRe: Need same in Silverlight 3... Pin
heyyan14-Jun-10 23:55
memberheyyan14-Jun-10 23:55 
GeneralHelp Pin
eman.tabbara9-Dec-09 19:58
membereman.tabbara9-Dec-09 19:58 
Questionmulti account? Pin
resideozsoy5-Oct-09 0:56
memberresideozsoy5-Oct-09 0:56 
QuestionCan i change? Pin
yukonn20-Aug-09 6:15
memberyukonn20-Aug-09 6:15 
GeneralRoutedEvent question Pin
mvtongeren30-Jun-09 21:41
membermvtongeren30-Jun-09 21:41 
QuestionConveting the Outlook Control to Silverlight Pin
Anil_gupta24-May-09 6:27
memberAnil_gupta24-May-09 6:27 
GeneralCreating an OutLook Calendar using WPF (Part 1) Pin
Member 263050330-Dec-08 8:29
memberMember 263050330-Dec-08 8:29 
GeneralMy vote of 2 Pin
Charles Perreault17-Dec-08 7:01
memberCharles Perreault17-Dec-08 7:01 
GeneralPragtig Pin
mwdiablo28-Oct-08 10:07
membermwdiablo28-Oct-08 10:07 
GeneralRe: Pragtig Pin
rudigrobler31-Oct-08 0:48
memberrudigrobler31-Oct-08 0:48 
GeneralAdding Appointments Pin
dennis oneill22-Oct-08 21:20
memberdennis oneill22-Oct-08 21:20 
QuestionDate format US? Pin
PaulLinton22-Oct-08 17:12
memberPaulLinton22-Oct-08 17:12 
AnswerRe: Date format US? Pin
PaulLinton22-Oct-08 17:41
memberPaulLinton22-Oct-08 17:41 
AnswerRe: Date format US? Pin
rudigrobler22-Oct-08 20:04
memberrudigrobler22-Oct-08 20:04 
GeneralFantastic Pin
quicoli22-Oct-08 0:45
memberquicoli22-Oct-08 0:45 
GeneralRe: Fantastic Pin
rudigrobler22-Oct-08 0:51
memberrudigrobler22-Oct-08 0:51 
GeneralDate comparisons Pin
normanr21-Oct-08 23:31
membernormanr21-Oct-08 23:31 
GeneralRe: Date comparisons Pin
rudigrobler21-Oct-08 23:40
memberrudigrobler21-Oct-08 23:40 
GeneralVery cool! Pin
strictly8621-Oct-08 22:38
memberstrictly8621-Oct-08 22:38 
GeneralRe: Very cool! Pin
rudigrobler21-Oct-08 22:41
memberrudigrobler21-Oct-08 22:41 
GeneralA good start Pin
Sacha Barber21-Oct-08 22:35
mvpSacha Barber21-Oct-08 22:35 
GeneralRe: A good start Pin
rudigrobler21-Oct-08 22:40
memberrudigrobler21-Oct-08 22:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150624.2 | Last Updated 22 Oct 2008
Article Copyright 2008 by rudigrobler
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid