استخدام التحكم في DateTimePicker في سيناريو محدد
-
23-08-2019 - |
سؤال
يتعلق هذا السؤال بوظائف محددة أن عميل طلب طلب لي تطبيق تصميمه. في الأساس، يريد العميل أن يدفع DateTimePicker سؤالا بعد تحديد التاريخ.
ومع ذلك، فإن هذا يبدو بسيطا، وأواجه صعوبات في إنجاز هذه المهمة البسيطة.
- إذا كنت موجه onlloseup - لن تنفذ إدخالات لوحة المفاتيح هذا الحدث
- إذا كنت موجه onvaluechanged - حرائق الأحداث في كل مرة يتم فيها تغيير التاريخ
- إذا كنت موجه onleave - حرائق الحدث إلى حد ما. لا ينطلق عند النقر فوق Toolstrip على سبيل المثال. أرغب في تجنب هذه الطريقة، حيث أن الحرائق فقط بمجرد النقر فوق المستخدم بعيدا عن عنصر التحكم.
في الأساس، أحاول التفكير في أفضل طريقة لموجه المستخدم بعد تحديد تاريخ من عنصر تحكم DatetimeMepicker.
ليس لدي أي مشاكل في بناء عنصر تحكم مخصص أيضا. لقد بدأت في جعل واحدة منذ أن كنت بحاجة أيضا للسماح بالقيم الفارغة.
المحلول 3
انتهى بي الأمر ترميز عنصر تحكم مخصص للتعامل مع هذه الطريقة الصحيحة. قمت بإنشاء مربع نص مع زر، وأضاف عنصر تحكم Monthcalendar أيضا.
يقوم زر TextBox + فتح عنصر التحكم Monthcalendar. الطريقة الوحيدة لاختيار DateTime الآن هي عبر Monthcalendar. لا يمكنك تحديد من مربع النص. لقد أنشأت أيضا حدثا مخصصا ينطلق عند تحديد التاريخ. يعمل تماما. الرمز أدناه:
Public Class CustomDatePicker
'Variables
Friend WithEvents cal As MonthCalendar
Private _isCalendarVisible As Boolean = False
Private _currentSelectedDate As DateTime = Nothing
'Events
Public Event OnDateTimeSet(ByVal sender As Object, ByVal dateValue As DateTime)
Public Event OnDateCleared(ByVal sender As Object)
'Constructor
Public Sub New()
InitializeComponent()
End Sub
'Onload
Private Sub CustomDatePicker_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Initially setup calendar
cal = New MonthCalendar
cal.Name = "Calendar"
cal.MaxSelectionCount = 1
cal.BringToFront()
cal.Location = New Point(Me.Location.X + 5, Me.Location.Y + 25)
Me.Parent.Controls.Add(cal)
cal.Hide()
_isCalendarVisible = False
End Sub
'Returns the currently selected date from the TextBox field
Public ReadOnly Property CurrentSelectedDate()
Get
Return _currentSelectedDate
End Get
End Property
'Display calendar
Private Sub ShowCalendar()
'Close any other custom date controls that are open on the parent form
Dim cont As Control
For Each cont In Parent.Controls
If (cont.GetType().Name = "CustomDatePicker") Then
CType(cont, CustomDatePicker).HideCalendar()
End If
Next
'display the calendar
If Not (_isCalendarVisible) Then
tbxSelectedDate.BackColor = Color.Cornsilk
cal.BringToFront()
cal.Show()
cal.Focus()
_isCalendarVisible = True
btnCalendarToggle.Checked = True
End If
End Sub
'Hide the Calendar
Private Sub HideCalendar()
If (_isCalendarVisible) Then
tbxSelectedDate.BackColor = Color.White
cal.Hide()
_isCalendarVisible = False
btnCalendarToggle.Checked = False
tbxSelectedDate.Focus()
End If
End Sub
'Display the selected datetime into the textbox
Private Sub SetDateTime()
Me.tbxSelectedDate.Text = FormatDateTime(cal.SelectionRange.Start, DateFormat.LongDate)
_currentSelectedDate = FormatDateTime(cal.SelectionRange.Start, DateFormat.LongDate)
RaiseEvent OnDateTimeSet(Me, _currentSelectedDate)
End Sub
'Event when selection is made in the Calendar
Private Sub Calendar_Selection(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DateRangeEventArgs) Handles cal.DateSelected
SetDateTime()
HideCalendar()
End Sub
'Handle the keyboard events associated with the calendar control
Private Sub Calendar_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cal.KeyPress
If e.KeyChar = ChrW(Keys.Return) Then
SetDateTime()
HideCalendar()
ElseIf e.KeyChar = ChrW(Keys.Escape) Then
HideCalendar()
End If
End Sub
'Handles keypresses on the textbox field
Private Sub tbxSelectedDate_KeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles tbxSelectedDate.KeyUp
If (e.KeyCode = Keys.Down) Then
ShowCalendar()
ElseIf (e.KeyCode = Keys.Delete) Then
tbxSelectedDate.Text = ""
End If
End Sub
'Show the calendar when button is clicked
Private Sub btnCalendarToggle_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btnCalendarToggle.MouseUp
ToggleCalendar()
End Sub
'Show the calendar when button is 'clicked' via ENTER on keyboard
Private Sub btnCalendarToggle_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles btnCalendarToggle.KeyPress
If e.KeyChar = ChrW(Keys.Return) Then
ToggleCalendar()
End If
End Sub
'Toggle calender. If on, turn off. If off, turn on.
Private Sub ToggleCalendar()
If Not (_isCalendarVisible) Then
ShowCalendar()
btnCalendarToggle.Checked = True
Else
HideCalendar()
btnCalendarToggle.Checked = False
End If
End Sub
'When textbox value is changed, check to see if it was cleared. If cleared, raiseevent.
Private Sub tbxSelectedDate_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tbxSelectedDate.TextChanged
If (tbxSelectedDate.Text = "") Then
_currentSelectedDate = Nothing
RaiseEvent OnDateCleared(Me)
End If
End Sub
نصائح أخرى
"حدد تاريخ" يعني:
- اختيار تاريخ مع الماوس، أو
- أدخل / تغيير تاريخ مع لوحة المفاتيح ثم نقل التركيز إلى عنصر تحكم آخر.
لذلك، ماذا عن مزيج من OnCloseUp
و OnValidate
/OnLeave
?
ابدأ بمشاهدة OnValueChanged
الأحداث. تعيين العلم المتغير إذا حرائق واحدة.
إذا حددوا باستخدام الماوس، فيمكنك إحضار المطالبة OnCloseUp
وإعادة تعيين العلم الذي تم تغييره. ثم مشاهدة ل OnValueChanged
الأحداث مرة أخرى.
متي OnValidate
أو OnLeave
حرائق، ويتم تعيين علمك (يفترض بعد تغيير التاريخ مع لوحة المفاتيح)، ثم إحضار المطالبة.
أود استخدام الحدث Onvaluechanged. بعد تغيير القيمة، اسأل السؤال. إذا أجبوا خطأ (مثال - س: هل أنت متأكد؟ ج: رقم) ثم إعادة تعيين Deasepicker والعودة التركيز عليه.
هذا المثال هو فوضوي قليلا ولكنه يعمل.
Private is_reset As Boolean = False
Private Sub DateTimePicker1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged
Dim answer As Integer
If Not is_reset Then
answer = MsgBox("Are you Sure?", MsgBoxStyle.YesNo)
is_reset = False
End If
If answer = MsgBoxResult.No Then
is_reset = True
DateTimePicker1.Value = Now
DateTimePicker1.Select()
End If