Here is a simple MonthPicker control. It displays a calendar-like list of the months as well as a dropdown to select a year. The user can click on the month names to select a month, and use the dropdown (or the buttons on either side) to change the year.
The control features properties like SelectedMonth, SelectedYear and SelectedDate (the date is just the selected year and month with a day of 1).
It also raises a SelectedMonthChanged event whenever the month, year or date changes.
You can choose whether to display full month names or abbreviated names via the MonthDisplay property.
The control also features a Culture property which allows you to set a culture ('language'). If you don't specify, the default culture of the user's computer will be used. The month names (actually the abbreviations are shown in the control) will be in the language of the selected culture.
Update 1
I am now rendering the months using a MonthPickerRenderer class. You can create a new class that inherits MonthPickerRenderer and use your own drawing code. There's methods you have to override such as OnPaintMonthBackground, OnPaintMonthText, etc, which provide you with a Graphics object and the coordinates (ClipRectangle) to draw, so you don't need to do any calculations or something; you just draw it in whatever way you like.
I added a DefaultRenderer to show you how it's done.
If you don't like all that work, but you do want to change the colors, you can also create your own MonthPickerColorTable and pass it to a new DefaultRenderer. Create a class that inherits MonthPickerColorTable and return the colors you want in the read-only property overrides. Then create a new DefaultRenderer and pass along your ColorTable:
Code:
MonthPicker1.Renderer = New Renderers.DefaultRenderer(New YourCustomColorTable())
That's it, the renderer will now use the colors you defined instead.
If you need an example, see the DefaultColorTable.
Due to the renderers I was able to make it look a lot more pretty, but as I said, if you don't like the looks, change it, it's easy!
Oh, the months now resize according to the size of the control, and you can specify how many columns you want. In the last screenshot it was the default of 4 columns, but here's a silly example with 9 columns (the number of columns must be between 1 and 12 obviously):
Update 2
The year selection dropdown and the next/previous year buttons on either side are now custom drawn as well, and included in the Renderers and ColorTables.
The 'Default' (example) renderer (and colortable) include the drawing for this part so you can see how it's done.
The year selection dropdown is still a ComboBox but it is hidden (except for the dropdown itself) behind a Panel to make it look a bit neater.
I've reworked the Renderer and ColorTable classes quite a bit. The ColorTables no longer use regular Colors, but GradientColors and SelectableColors.
A GradientColor is just a set of two colors (one for the top of the gradient, one for the bottom) with a few helpful methods such as GetBrush (to create a LinearGradientBrush from these two colors) and GetPen (to create a gradient pen).
A SelectableColor is an object with three GradientColors: one for the normal state, one for the selected state and one for the hovering state (mouse hovering over the element to draw).
These classes allowed me to make the ColorTables and Renderers a bit neater.
Finally, I made an example of a custom renderer to mimic the Windows 7 MonthCalendar control in month view mode. Drawing is all done in the Windows7CalendarRenderer. I've included a couple of helper methods in the Helpers class (available via MonthPickerRenderer.DrawingHelpers) that draw rounded rectangles to make life easier.
As you can see, it's quite easy to make a renderer like this and it looks nearly spot on in my opinion
Known bugs after update 2:
The previous/next year buttons and the year label do not repaint when the mouse is hovering over them. The Renderers and ColorTables support a Hovering color and will draw them if the panels in question would get repainted, but for some reason they don't so you never see it.
Feel free to edit it in any way you want and enjoy.
Last edited by NickThissen; Jun 15th, 2011 at 05:25 PM.
This is a great start, I did notice you can re-size the control but it doesn't expand the months size if you go bigger than the default, easy to fix though.
Where you planning on adding in day's to this, like you can pick a day of a certain year and it'll be "selected" while you can go pick another day (of a different month or year) and that would define the range?
Currently using VS 2015 Enterprise on Win10 Enterprise x64.
Yes, the days should become resizable if I just dock the labels to fill, but I was lazy and used a FlowLayoutPanel. If you use a TableLayoutPanel instead (with a fixed number of rows/columns) then it would work. But then (in my opinion) the number of rows/columns should be configurable, which was too much work for me this morning
In my case, you can resize the control so that more rows or more columns are displayed (3,3,3,3 for example, or 4,4,4. Or 2,2,2,2,2,2).
I guess both ways have their advantages, but its easy enough to switch around.
As for adding days: definitely not. The whole point is that you can only select months and not individual days in that month (otherwise you'd use the built in Calendar control). I might implement selecting a range of months though, that's a good idea.
Yes, the days should become resizable if I just dock the labels to fill, but I was lazy and used a FlowLayoutPanel. If you use a TableLayoutPanel instead (with a fixed number of rows/columns) then it would work. But then (in my opinion) the number of rows/columns should be configurable, which was too much work for me this morning
In my case, you can resize the control so that more rows or more columns are displayed (3,3,3,3 for example, or 4,4,4. Or 2,2,2,2,2,2).
I guess both ways have their advantages, but its easy enough to switch around.
As for adding days: definitely not. The whole point is that you can only select months and not individual days in that month (otherwise you'd use the built in Calendar control). I might implement selecting a range of months though, that's a good idea.
You could use a TableLayout control and not let the end user select the number of rows/cols and let them just deal with it.
I only asked about the days because of our xfire discussion last weekend on the topic, have you thought anymore about using slider controls to zoom out to span years and then zoom in to pick the month & days?
Currently using VS 2015 Enterprise on Win10 Enterprise x64.
New features:
- Months resize according to control size
- Number of columns shown is configurable (for example, 4 columns creates 3 rows of 4 months each. 6 columns creates 2 rows of 6 months, etc).
- Month underneath your mouse now highlights
- Completely configurable look by the use of a Renderer and/or ColorTable (see original post for details).
Things I'm planning:
- Make the year dropdown + buttons custom drawn as well and include them in the Renderer
- Create a Windows 7 style Renderer.
Short list of updates:
- Ability to show full month names or abbreviations using MonthDisplay property
- Header (next/previous year buttons and year label) custom drawn and included in Renderer
- Renderers and ColorTables reworked quite a bit to allow for easier specification and grouping of gradient colors as well as normal/hovering/selected groups.
- Windows 7 MonthCalendar custom renderer included as another example of how to completely redesign the control (very easy to do!)
Great control! I think the Windows 7 Aero-rendered version would look better with the header still a gradient, though. Could you make that a designer option?