简体   繁体   中英

How can I set the datetimepicker dropdown to show Months only

So instead of this showing up on clicking the dropdown menu.

在此处输入图像描述

I want the dropdown to be like this when clicked.

在此处输入图像描述

Thanks a lot for any help. :)

Why you need to do this? If you want to display Months only then easier way is to have a list of months in Combox.

However I found something for you on msdn. Have a look here https://social.msdn.microsoft.com/Forums/en-US/7bdca56f-719e-44bf-be6d-a9600dfa8f78/wpf-datepicker-for-months-only?forum=wpf

Using the windows messages approach , you can detect month calendar control display and force month view and you can detect view changes and close the month calendar control on month to day views change (after a month selection).

The easiest way to implement it is to override DateTimePicker.

public class MonthPicker : DateTimePicker
{
    // initialize Format/CustomFormat to display only month and year.
    public MonthPicker()
    {
        Format = DateTimePickerFormat.Custom;
        CustomFormat = "MMMM yyyy";
    }

    // override Format to redefine default value (used by designer)
    [DefaultValue(DateTimePickerFormat.Custom)]
    public new DateTimePickerFormat Format
    {
        get => base.Format;
        set => base.Format = value;
    }

    // override CustomFormat to redefine default value (used by designer)
    [DefaultValue("MMM yyyy")]
    public new string CustomFormat
    {
        get => base.CustomFormat;
        set => base.CustomFormat = value;
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_NOFITY)
        {
            var nmhdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
            switch (nmhdr.code)
            {
                // detect pop-up display and switch view to month selection
                case -950:
                {
                    var cal = SendMessage(Handle, DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
                    SendMessage(cal, MCM_SETCURRENTVIEW, IntPtr.Zero, (IntPtr)1);
                    break;
                }

                // detect month selection and close the pop-up
                case MCN_VIEWCHANGE:
                {
                    var nmviewchange = (NMVIEWCHANGE)Marshal.PtrToStructure(m.LParam, typeof(NMVIEWCHANGE));
                    if (nmviewchange.dwOldView == 1 && nmviewchange.dwNewView == 0)
                    {
                        SendMessage(Handle, DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero);
                    }

                    break;
                }
            }
        }
        base.WndProc(ref m);
    }

    private const int WM_NOFITY = 0x004e;
    private const int DTM_CLOSEMONTHCAL = 0x1000 + 13;
    private const int DTM_GETMONTHCAL = 0x1000 + 8;
    private const int MCM_SETCURRENTVIEW = 0x1000 + 32;
    private const int MCN_VIEWCHANGE = -750;

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

    [StructLayout(LayoutKind.Sequential)]
    private struct NMHDR
    {
        public IntPtr hwndFrom;
        public IntPtr idFrom;
        public int code;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct NMVIEWCHANGE
    {
        public NMHDR nmhdr;
        public uint dwOldView;
        public uint dwNewView;
    }
}

Try the following code:

DateTime newDateValue = new DateTime(dateTimePicker_month.Value.Year, 1, 1);
dateTimePicker_month.Value = newDateValue;
dateTimePicker_month.Format = DateTimePickerFormat.Custom;
dateTimePicker_month.CustomFormat = "MMM-yyyy";
dateTimePicker_month.ShowUpDown = true;

You have to add (1,1) for february month which having 28/29 days to ascertain the all the month values.If you want the query to select month.Following is an example:

string month = dateTimePicker_month.Value.Month.ToString();
string year = dateTimePicker_month.Value.Year.ToString();

use the following query to select month:

select CAST(date AS DATE) from table where DATEPART(month, date)  = '" + month + "' and DATEPART(year,date) = '" + year + "' 

Try using Format properties:

 dateTimePicker.Format = DateTimePickerFormat.Custom;
 dateTimePicker.CustomFormat = "MM";

As didn't work in my case I modified Orance's answer, putting this in a class inherited from DateTimePicker :

    protected override void WndProc(ref Message m)
{
    if (_MonthSelectStyle)
    {
        if (m.Msg == 0X204E) // = Win32Messages.WM_REFLECT_NOTIFY
        {
            var nmhdrI = (NMHDR)(Marshal.PtrToStructure(m.LParam, typeof(NMHDR)));
            switch (nmhdrI.code)
            {
                case -754: // Win32Messages.DTN_DROPDOWN
                    var cal = SendMessage(m.HWnd, WinApi.Win32Messages.DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
                    SendMessage(cal, WinApi.Win32Messages.MCM_SETCURRENTVIEW, IntPtr.Zero, (IntPtr)1);
                    break;
                case -759: // Win32Messages.DTN_DATETIMECHANGE
                    WinApi.SendMessage(Handle, WinApi.Win32Messages.DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero);
                    break;
            }
        }
    }
    base.WndProc(ref m);
}

And the VB equivalent:

    Protected Overrides Sub WndProc(ByRef m As Message)
    If _MonthSelectStyle Then
        If m.Msg = &H204E Then ' WM_REFLECT_NOTIFY  '&H204E   
          Dim nmhdrI = CType(Marshal.PtrToStructure(m.LParam, GetType(NMHDR)), NMHDR)
            Select Case nmhdrI.code
                Case -754 ' Win32Messages.DTN_DROPDOWN '-754  
                    Dim cal = SendMessage(m.HWnd, WinApi.Win32Messages.DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero)
                    SendMessage(cal, WinApi.Win32Messages.MCM_SETCURRENTVIEW, IntPtr.Zero, CType(1, IntPtr))
                Case -759 ' Win32Messages.DTN_DATETIMECHANGE '-759  
                    WinApi.SendMessage(Handle, WinApi.Win32Messages.DTM_CLOSEMONTHCAL, IntPtr.Zero, IntPtr.Zero)
            End Select
        End If
    End If
    MyBase.WndProc(m)
End Sub

The class "public class MonthPicker: DateTimePicker" inherits from DateTimePicker, It is not a custom user control.

That's why I can't see the MonthPicker in my control box. Am I missing something? How to add the MonthPicker.cs to my code, and use it as a custom control?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM