0

我对 DateTimePicker 有疑问,它很容易重现,感觉就像控件本身的错误,但我想确保我没有误解任何内容。

首先,此代码非常简单,使用 DateTimePicker 创建一个 WinForms 应用程序(我们的项目在 .net 4.0 中,但我尝试在 .net 4.5 中创建它,同样的问题)。选择器本身具有自定义格式,格式为“HH:mm”,并且 ShowUpDown 设置为 true。它有一个验证方法如下:

private void dateTimePicker1_Validating(object sender, CancelEventArgs e)
{
    dateTimePicker1.Value = DateTime.Now;
}

在该行上设置断点。

确保在应用程序中有另一个控件,以便您可以跳出 DateTimePicker 以触发验证。

现在,在程序中导航到 DateTimePicker 并在例如小时字段中输入“202”。这看起来就像你先写了 20,当你写第二个“2”时,它现在只是字段中的 2。

现在从 DateTimePicker 中跳出。这将触发验证断点。请注意 DateTimePicker 现在的值是如何设置为 20 小时的日期。让该行再次执行并观察 DateTimePicker 的值。现在将值 os 02 改为小时(不是(!!) DateTime.Now 的值)

因此,在将值设置为 DateTime.Now 之后,它以某种方式将值更改为在 DateTimePicker 中输入的先前未完成的值。

怎么会这样,有什么办法可以解决这个问题吗?

4

2 回答 2

1

我无法重现这一点。Windows 版本非常重要,许多常见的控制怪癖在以后的版本中得到了修复。我在 Windows 8 上。

然而,这是一个常见问题,这些控件在触发事件时对您对它们执行的操作很挑剔。他们往往会在他们触发事件后运行代码,这很可能会使您所做的事情无效。Validating 事件特别棘手,因为它是作为焦点更改的副作用而引发的。如果 DTP 还没有收到同样的通知,那就有麻烦了。非常典型的事件订购麻烦。如果您实际上没有使用 Validating 来验证数据,请支持 Leave 事件。

听起来像是一场比赛。此类排序问题的一般解决方案是在事件触发并且代码执行不再在控件代码中之后运行您的代码。您可以使用表单的 BeginInvoke() 方法优雅地完成此操作。目标在您的程序重新进入消息循环并且 UI 回到静止状态后运行。像这样:

    private void dateTimePicker1_Validating(object sender, CancelEventArgs e) {
        this.BeginInvoke(new Action(() => dateTimePicker1.Value = DateTime.Now));
    }
于 2013-04-08T12:57:07.447 回答
0

在验证事件期间,我看到了您解释的行为,但是一旦验证事件完成,值就会设置为DateTime.Now.

假设您希望它DateTime.Now在 Validating 事件本身期间将 DateTimepicker 控件的值设置为,我发现设置该值两次显示该值更改为DateTime.Now-

dateTimePicker1.Value = DateTime.Now;

dateTimePicker1.Value = DateTime.Now;

于 2013-04-08T12:26:15.777 回答