.net – 如何获取DataGridView的DateTimePicker checkstate值?

我有一个DataGridview,其中有一个DataTimePickerColumn,它的DateTimePickerCell包含checkstate.编辑checkstate后如何获取checkstate值? 最佳答案 创建一个继承自DateTimePicker的控件并处理DTN_DATETIMECHANGE通知.然后处理DataGridView的EditingControlShowing事件,为DateTimePicker的新CheckedChanged事件添加处理程序,甚至可以使用DateTimePickerEx创建自己的DataGridViewColumn和Cell类型作为EditingControl:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;

public class DateTimePickerEx : DateTimePicker
{
  private bool _checked;
  private const int WM_REFLECT = 0x2000;
  public event CheckedChangedEventHandler CheckedChanged;
  public delegate void CheckedChangedEventHandler(object sender, System.EventArgs e);

  public DateTimePickerEx()
  {
    this._checked = this.Checked;
  }

  private void WmDateTimeChange(ref Message m)
  {
    NMDATETIMECHANGE nmdatetimechange = m.GetLParam(typeof(NMDATETIMECHANGE));

    if (nmdatetimechange.dwFlags == GetDateTimeValues.GDT_NONE) {
      if (this.ShowCheckBox && !this.Checked) {
        this._checked = false;
        if (CheckedChanged != null) {
          CheckedChanged(this, EventArgs.Empty);
        }
      }
    } else {
      if (this.ShowCheckBox && this.Checked && !this._checked) {
        this._checked = true;
        if (CheckedChanged != null) {
          CheckedChanged(this, EventArgs.Empty);
        }
      }

      this.Value = SysTimeToDateTime(nmdatetimechange.st);
    }

    m.Result = IntPtr.Zero;
  }

  private bool WmReflectCommand(ref Message m)
  {
    if (m.HWnd == this.Handle) {
      long code = NMHDR.FromMessage(m).code;

      switch (code) {
        case FWEx.Win32API.DateTimePickerNotifications.DTN_DATETIMECHANGE:
          this.WmDateTimeChange(ref m);
          return true;
      }

      return false;
    }
  }

  [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
  protected override void WndProc(ref System.Windows.Forms.Message m)
  {
    if (m.Msg != 71 && m.Msg != 513) {
      switch ((WindowsMessages)m.Msg) {
        case WindowsMessages.WM_NOTIFY + WM_REFLECT:
          if (!this.WmReflectCommand(ref m)) {
            break;
          }

          return;

          break;
      }
    }

    base.WndProc(m);
  }

  private System.DateTime SysTimeToDateTime(SYSTEMTIME st)
  {
    return new System.DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second);
  }

  /// <summary>
  /// This structure contains information about a change that has taken place in a date and time picker (DTP) control.
  /// This structure is used with the DTN_DATETIMECHANGE notification message.
  /// </summary>
  /// <remarks></remarks>
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  public struct NMDATETIMECHANGE
  {
    /// <summary>
    /// NMHDR structure that contains information about the notification message.
    /// </summary>
    public NMHDR nmhdr;
    /// <summary>
    /// Specifies if the control was set to no date status (for DTS_SHOWNONE only).
    /// Also specifies whether the contents of the st member are valid and contain current time information.
    /// </summary>
    public GetDateTimeValues dwFlags;
    /// <summary>
    /// SYSTEMTIME structure that contains information about the current system date and time. 
    /// </summary>
    public SYSTEMTIME st;
  }

  /// <summary>
  /// This structure contains information about a message.
  /// The pointer to this structure is specified as the lParam member of the WM_NOTIFY message.
  /// </summary>
  [StructLayout(LayoutKind.Sequential)]
  public struct NMHDR
  {
    /// <summary>
    /// Window handle to the control sending a message.
    /// </summary>

    public IntPtr hwndFrom;
    /// <summary>
    /// Identifier of the control sending a message.
    /// </summary>

    public IntPtr idFrom;
    /// <summary>
    /// Notification code. This member can be a control-specific notification code or it can be one of the common notification codes. The following values are supported if you include mouse support in your device platform:
    /// - NM_RCLICK
    /// - NM_RDBCLICK
    /// </summary>

    public int code;
    public static NMHDR FromMessage(System.Windows.Forms.Message msg)
    {
      return (NMHDR)msg.GetLParam(typeof(NMHDR));
    }
  }

  /// <summary>
  /// Specifies a date and time, using individual members for the month, day, year, weekday, hour, minute, second, and millisecond. 
  /// The time is either in coordinated universal time (UTC) or local time, depending on the function that is being called.
  /// </summary>
  /// <remarks>
  /// It is not recommended that you add and subtract values from the SYSTEMTIME structure to obtain relative times.
  /// </remarks>
  public struct SYSTEMTIME
  {
    /// <summary>
    /// The year. The valid values for this member are 1601 through 30827.
    /// </summary>
    public short Year;
    /// <summary>
    /// The month.
    /// </summary>
    public short Month;
    /// <summary>
    /// The day of the week. Sunday = 0.
    /// </summary>
    public short DayOfWeek;
    /// <summary>
    /// The day of the month. The valid values for this member are 1 through 31.
    /// </summary>
    public short Day;
    /// <summary>
    /// The hour. The valid values for this member are 0 through 23.
    /// </summary>
    public short Hour;
    /// <summary>
    /// The minute. The valid values for this member are 0 through 59.
    /// </summary>
    public short Minute;
    /// <summary>
    /// The second. The valid values for this member are 0 through 59.
    /// </summary>
    public short Second;
    /// <summary>
    /// The millisecond. The valid values for this member are 0 through 999.
    /// </summary>
    public short Milliseconds;
  }

  public enum GetDateTimeValues
  {
    /// <summary>
    /// Error.
    /// </summary>
    GDT_ERROR = -1,
    /// <summary>
    /// The control is not set to the no date status.
    /// The st member contains the current date and time. 
    /// </summary>
    GDT_VALID = 0,
    /// <summary>
    /// The control is set to no date status. 
    /// The no date status applies only to controls that are set to the DTS_SHOWNONE style. 
    /// </summary>
    GDT_NONE = 1
  }

  public enum WindowsMessages
  {
    /// <summary>
    ///Sent by a common control to its parent window when an event has occurred or the control requires some information.
    /// </summary>
    WM_NOTIFY = 0x4e
  }

  public enum DateTimePickerNotifications
  {
    DTN_FIRST = -740,
    DTN_LAST = -745,
    DTN_FIRST2 = -753,
    DTN_LAST2 = -799,
    DTN_DATETIMECHANGE = DTN_FIRST2 - 6,
    DTN_USERSTRING = DTN_FIRST2 - 5,
    DTN_WMKEYDOWN = DTN_FIRST2 - 4,
    DTN_FORMAT = DTN_FIRST2 - 3,
    DTN_FORMATQUERY = DTN_FIRST2 - 2,
    DTN_DROPDOWN = DTN_FIRST2 - 1,
    DTN_CLOSEUP = DTN_FIRST2
  }
}

处理DataGridView.EditingControlShowing上的DateTimePickerEx.CheckedChanged:

    private void dgv_EditingControlShowing(System.Object sender, System.Windows.Forms.DataGridViewEditingControlShowingEventArgs e)
    {
        switch (this.dgv.CurrentCellAddress.X) {
              case 0: // your DateTimePickerEx column number
                    DateTimePickerEx dtp = e.Control as DateTimePickerEx;

                    if (dtp != null) {
                          dtp.CheckedChanged += (object sen, EventArgs ea) => {
                                    //TODO: Add your code here
                          };
                    }

                break;
        }
    }
点赞