【问题标题】:How can I programmatically close the dropdown calendar of a datetimepicker or update the dropdown calendar to reflect the .Value property?如何以编程方式关闭 datetimepicker 的下拉日历或更新下拉日历以反映 .Value 属性?
【发布时间】:2013-02-21 23:33:49
【问题描述】:

请帮忙?!问题是因为我有一个使用 datetimepicker 控件的旧用户控件。如果 datetimepicker 的文本框中没有要显示的日期,则 .Value 属性设置为 DateTimePicker.MinimumDateTime。如果 .Value 是 DateTimePicker.MinimumDateTime,OnValueChanged 会将 CustomFormat 更新为“”。否则,CustomFormat 为“yyy-MM-dd hh:mm:ss tt”。

问题 ==> 在 DropDown 事件中,我检查最小日期时间。如果 .Value 等于那个值,那么我将 .Value 更新为 DateTime.Now。当下拉日历显示时,日历设置为 1753-01-01,而文本框 (.Value) 显示 DateTime.Now。

如何让日历显示与在 DropDown 事件中更新的 .Value 属性相对应的日期?即使有一种方法可以在值从 DateTimePicker.MinimumDateTime 更改为 DateTime.Now 时“取消” DateTimePicker 上的第一个 DropDown 事件。现在我认为这可以工作,因为第二次(和后续时间)下拉显示日历 日历正确匹配文本框中显示的日期 (DateTimePicker.Value)。

这是我连接到有问题的 DateTimePicker 的事件的代码:

    private void ValueDatetimePickerOnKeyUp(Object sender, KeyEventArgs e)
    {
        if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back)
            return;
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        dp.Value = DateTimePicker.MinimumDateTime;
    }

    private void ValueDatetimePickerDropDown(Object sender, EventArgs e)
    {
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        if (dp.Value == DateTimePicker.MinimumDateTime)
            dp.Value = DateTime.Now;
    }

    private void ValueDatetimePickerValueChanged(Object sender, EventArgs e)
    {
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        dp.CustomFormat = dp.Value == DateTimePicker.MinimumDateTime ? " " : "yyyy-MM-dd hh:mm:ss tt";
    }

【问题讨论】:

  • 更新 .Value 属性时能否更新 .Text 属性?只是一个想法
  • @user959729 - 感谢您的回复。 .Text 属性不是问题。当 .Value 更新为 DateTime.Now 时,它将在文本框中显示当前日期/时间。问题是下拉的日历认为它是 1753 年 1 月 1 日,因为在我在 DropDown 事件中更新它之前是 .Value 属性的值。我需要一种方法让日历显示与文本框(.Text 和 .Value)相同的年、月、日。我希望我很清楚。我觉得我在兜圈子。如果您需要更多信息,请告诉我。再次感谢。
  • 您是否尝试过调用 .Invalidate()?这将强制控件绘制并希望具有正确的值。此外,您可能想尝试 beginUpdate() 和 endUpdate()。更多的想法。我还没有测试过这些
  • 也看看这篇文章:stackoverflow.com/questions/4174214/…
  • @user959729 - 再次感谢您的回复。我认为没有 BeginUpdate() 或 EndUpdate()。不是我无论如何都能找到的。我尝试了 Invalidate() 和 Invalidate(true) 无济于事。啊。太令人沮丧了。我晚上要离开。我期待着早上的任何回应。再次感谢。

标签: c# .net winforms datetimepicker


【解决方案1】:

我有一些时间来解决这个问题。这有点 hacky,但基本上在 datetimepicker 的 DropDown 事件处理程序中将 ShowUpDown 设置为 true,然后调用 Closeup 事件处理程序将 ShowUpDown 设置回 false。这将关闭下拉日历并强制用户再次打开它,然后日历上将显示正确的日期,而不是 1753 年 1 月 1 日。 OnKeyUp 事件处理程序只允许用户在按下 DEL 或 Backspace 键时将 datetimepicker 的文本框值清空。

    private void ValueDatetimePickerOnKeyUp(Object sender, KeyEventArgs e)
    {
        //if user presses backspace or delete key then clear the date/time
        if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back)
            return;
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        dp.Value = DateTimePicker.MinimumDateTime;
    }

    private void ValueDatetimePickerCloseUp(Object sender, EventArgs e)
    {
        var dp = (DateTimePicker) sender;
        if(dp == null)
            return;
        dp.ShowUpDown = false;
    }

    private void ValueDatetimePickerDropDown(Object sender, EventArgs e)
    {
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        if (dp.Value == DateTimePicker.MinimumDateTime)
        {
            dp.Value = DateTime.Now;
            dp.ShowUpDown = true;
            Invoke((MethodInvoker) (() => ValueDatetimePickerCloseUp(dp, new EventArgs())));
        }
    }

    private void ValueDatetimePickerValueChanged(Object sender, EventArgs e)
    {
        var dp = (DateTimePicker)sender;
        if (dp == null)
            return;
        dp.CustomFormat = dp.Value == DateTimePicker.MinimumDateTime ? " " : "yyyy-MM-dd HH:mm:ss tt";
    }

【讨论】:

    【解决方案2】:

    创建您自己的控件并添加:

    #region IsInputKey(Keys keyData)
            protected override bool IsInputKey(Keys keyData)
            {
                if (keyData == Keys.Tab
                    //|| keyData.Equals(Keys.Up)
                    //|| keyData.Equals(Keys.Down)
                    //|| keyData.Equals(Keys.Left)
                    //|| keyData.Equals(Keys.Right)
                    || keyData.Equals(Keys.Enter)
                    || keyData.Equals(Keys.Escape)
                    || keyData.Equals(Keys.Space)
                    )
                    return true;
    
                return base.IsInputKey(keyData);
            }
            #endregion
    

    这将允许您希望在 KeyDown 事件上传递的所有键。 ;D高频!!! 并且也可以与其他控件一起使用,例如 TextBox、DataGridView 等。

    【讨论】:

      【解决方案3】:

      如果只需要禁止打开下拉菜单,您可以使用更简单的解决方案。

      只需在 DropDown 事件中切换 ShowUpDown 属性。 将 this 更改为您的控件名称。

      private void MyDropDown(object sender, EventArgs e)
      {
          bool value = this.ShowUpDown;
          this.SuspendLayout();
          this.ShowUpDown = !value;
          this.ShowUpDown = value;
          this.ResumeLayout();
      }
      

      添加事件处理程序。

      this.DropDown += MyDropDown;
      

      将 DoubleBuffered 属性设置为 true 以避免闪烁可能会很方便。

      Type type = this.GetType();
      System.Reflection.PropertyInfo property;
      property = type.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
      property.SetValue(control, true, null);
      

      或者,您可以检查 ShowUpDown 属性是否已经为假,因此它仅适用于日历下拉菜单。

      private void MyDropDown(object sender, EventArgs e)
      {
          if (this.ShowUpDown == false)
          {
              this.SuspendLayout();
              this.ShowUpDown = true;
              this.ShowUpDown = false;
              this.ResumeLayout();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-03
        • 1970-01-01
        • 2019-01-20
        • 2018-01-20
        相关资源
        最近更新 更多