WPF MonthPicker: HowTo

As I was making a WPF Gui I needed a control that would allow for a user to select only a month (and a year). There was no such control, they’d even removed the standard date picker from the WPF library!
I found the WPF Toolkit which contained a calendar control (just what I needed) and I decided to give it a shot. The calendar was perfect, it even allowed me to show only months in a year instead of days in a month. You could have it in three different modes:

The three different display modes
The different display modes

The problem was that I couldn’t find a way to get the selected date from the control without forcing the user to actually selecting a day. The way it works is that if you set DisplayMode to Year, which I did, you force the user to first select month and after that select day. I only wanted them to select month!
This could be handled by sort of locking the control via its events. This is what I did:

WPF:

<Window x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" xmlns:my="http://schemas.microsoft.com/wpf/2008/toolkit">
    <Grid>
        <my:Calendar Margin="39,54,60,40" Name="calendar1" DisplayMode="Year" DisplayModeChanged="calendar1_DisplayModeChanged" DisplayDateChanged="calendar1_DisplayDateChanged" />
        <TextBox Height="23" Margin="38,19,60,0" Name="textBox1" VerticalAlignment="Top" />
    </Grid>
</Window>

C#:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }
 
    private void calendar1_DisplayModeChanged(object sender, Microsoft.Windows.Controls.CalendarModeChangedEventArgs e)
    {
        if (calendar1.DisplayMode != Microsoft.Windows.Controls.CalendarMode.Year)
        {
            calendar1.DisplayMode = Microsoft.Windows.Controls.CalendarMode.Year;
        }
    }
 
    private void calendar1_DisplayDateChanged(object sender, Microsoft.Windows.Controls.CalendarDateChangedEventArgs e)
    {
        if (textBox1 != null) //Because the calendar may render prior to the textbox
        {
            string year = calendar1.DisplayDate.Year.ToString();
            string month = calendar1.DisplayDate.Month.ToString();
 
            if (calendar1.DisplayDate.Month < 10)
                month = "0" + month;
 
            textBox1.Text = string.Format("{0}-{1}", year, month);
        }
    }
}

This is how it could look:

A screenshot of how it could look
A MonthPicker app!

4 thoughts on “WPF MonthPicker: HowTo

  1. Hi, I have created the same thing as you described here, but can you check what happens when you click on a month, and then move your mouse outside of the calendar control??
    in my case when I click for instance an feb (and it is selected) then I move my mouse down and leave the control, then the last hovered month stays selected??? so in my case i click feb, move mouse down and leave the control, then okt is still highlighted !
    do you experience the same behaviour? or do you have a work-around? thx in advance greetz

    1. Hello Frank!

      What you describe is what happens if you click on one month, hold the mouse button down, and then move your cursor, but I believe that is the expected behavior. If you just click a month and then hover I assume you have no problem?
      As a solution you could try to trigger the MouseDown event on your calendar and send the month selected on MouseDown to your calendar when either focus is lost or MouseUp is triggered and then set the calendar value to that.

      1. Hi, my colleague found a perfect work around for this bug :

        private void MyCalendar_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
        if (Mouse.Captured is CalendarItem) { Mouse.Capture(null); }
        }

        thx

Leave a Reply