|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionMicrosoft 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 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 CalendarLedgerItem and CalendarLedger
The ledger indicates the timeslot time. CalendarTimeslotItem
Each day is divided into 30 minute slots (represented by public static readonly RoutedEvent AddAppointmentEvent =
EventManager.RegisterRoutedEvent("AddAppointment", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(CalendarTimeslotItem));
CalendarAppointmentItem
<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! CalendarDayThe protected override DependencyObject GetContainerForItemOverride()
{
return new CalendarAppointmentItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return (item is CalendarAppointmentItem);
}
Each “item” added to the TimeslotPanelThe last part we have to cover before we look at the calendar control is the <ItemsPanelTemplate>
<local:TimeslotPanel />
</ItemsPanelTemplate>
CalendarThe public static readonly RoutedEvent AddAppointmentEvent =
CalendarTimeslotItem.AddAppointmentEvent.AddOwner(typeof(CalendarDay));
Currently, the public static readonly DependencyProperty CurrentDateProperty =
DependencyProperty.Register("CurrentDate", typeof(DateTime), typeof(Calendar),
new FrameworkPropertyMetadata((DateTime)DateTime.Now,
new PropertyChangedCallback(OnCurrentDateChanged)));
The public static readonly RoutedCommand NextDay =
new RoutedCommand("NextDay", typeof(Calendar));
public static readonly RoutedCommand PreviousDay =
new RoutedCommand("PreviousDay", typeof(Calendar));
These commands are self explanatory! I have also created a very basic model:
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 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
And, that is it for part 1... If you found this article interesting, please vote for it, and also visit my blog!
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||