我有以下代码,当用户更改我的'结束'日期DateTinePicker控件上的日期时运行:
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If dtpEndDate.Value.Date < dtpStartDate.Value.Date Then
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
dtpEndDate.Value = Today
End If
End Sub
此过程似乎运行了两次,因为消息框会显示两次。
我有错误的事件,还是有更好的方法来管理它?
我尝试使用建议的变量进行编辑:
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If m_blndtpEndDateIsDone = False Then
If dtpEndDate.Value.Date < dtpStartDate.Value.Date Then
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
m_blndtpEndDateIsDone = True
dtpEndDate.Value = Today
Else
m_blndtpEndDateIsDone = False
End If
Else
m_blndtpEndDateIsDone = False
End If
wnd sub
不幸的是,它仍在发射两次......
我希望每次修改结束日期dtpicker并且日期在开始日期之前触发一次。
感谢
菲利普
答案 0 :(得分:3)
MessageBox可能非常麻烦。它将焦点从控件上拉开,并泵出自己的消息循环。这可能导致 re-entrancy 问题,这种问题使得DoEvents()如此臭名昭着。没有编写DateTimePicker控件来处理这个问题,它通常是一种笨拙的控制。
一个简单的解决方法是避免面对面的错误报告。 ErrorProvider组件可以很好地完成此任务。在表单上删除一个,并使您的代码看起来像这样:
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If dtpEndDate.Value.Date < dtpStartDate.Value.Date Then
ErrorProvider1.SetError(dtpEndDate, "The end date should be after the start date")
dtpEndDate.Value = Today
Else
ErrorProvider1.SetError(dtpEndDate, "")
End If
End Sub
你实际上可以避免MessageBox创建的重新入侵问题,你可以在DateTimePicker完成自己的事件处理之后通过显示它以后来实现。使用Control.BeginInvoke()在Winforms中优雅地完成。看起来像这样:
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If dtpEndDate.Value.Date < dtpStartDate.Value.Date Then
Me.BeginInvoke(New MethodInvoker(AddressOf reportDateProblem))
dtpEndDate.Value = Today
End If
End Sub
Private Sub reportDateProblem()
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Sub
答案 1 :(得分:0)
这曾经发生在我身上。
您可以证明您至少在 WebForms 中的两个地方处理事件:在asp页面和后面的代码中。如果我在后面的代码中签署“dtpEndDate_ValueChanged”方法之后我有语法“Handles dtpEndDate.ValueChanged”,那么我就不必在我的aspx中写入“OnClick =”dtpEndDate_ValueChanged“”或类似的东西。
当你在 WinForms 而不是在WebForms中时,请确保你没有
&lt;&lt; AddHandler dtpEndDate.ValueChanged,AddressOf Me.dtpEndDate_ValueChanged &gt;&gt;
或类似于Load方法或其他地方的某些内容。
希望它有所帮助,
伊夫
答案 2 :(得分:0)
您可以使用 dtpEndDate_Validating 事件
Private Sub dtpEndDate_Validating(sender As Object, e As CancelEventArgs)
If dtpEndDate.Value.[Date] < dtpStartDate.Value.[Date] Then
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.[Error])
End If
e.Cancel = True
End Sub
或强>
如果你想要使用你的事件(dtpEndDate_ValueChanged),那么在表单中定义一个布尔变量并将值设置为false。在您执行第一次消息框后的事件中,将变量设置为true。并检查此变量
Dim isDone As Boolean = False
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If Not isDone Then
If dtpEndDate.Value.Date < dtpStartDate.Value.Date Then
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
IsDone = True
dtpEndDate.Value = Today
End If
End If
End Sub
答案 3 :(得分:0)
试试这个,
Private Sub dtpEndDate_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpEndDate.ValueChanged
If (dtpEndDate.Value.Date < dtpStartDate.Value.Date) And Not dtpEndDate.Value = Today Then
MessageBox.Show("The end date should be after the start date", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
dtpEndDate.Value = Today
End If
End Sub
您要在dtpEndDate
之前today's date
重置日期,因此dtpStartDate
应小于today
,因此使用该版本不会发生逻辑冲突上面的代码。