WinForm DateTimePicker 忧郁。是我吗?

发布于 2024-10-06 21:35:16 字数 579 浏览 6 评论 0原文

我希望能够使用 DateTimePicker 控件接受 NULL 日期。

“Checked”属性似乎旨在指定控件是“保留日期”还是现在。但是,当“未选中”时,日期仍然显示,尽管它显示为已禁用。对我来说,这让人分心。如果未选中的复选框的目的是表明没有日期值,为什么文本框中会出现禁用或其他日期值?在我看来,如果未选中该控件,则文本框应该为空,并且当用户真正想要“无值”时看到变暗的日期值会分散注意力。

如果用户打开复选框,那么我希望能够将默认值放入文本框中。

我正在考虑创建一个在 dateTimePicker 控件和 textBox 之间切换的用户控件,但我讨厌经历这个麻烦。

我尝试查看 Telerik 的 DateTimePicker,但试图从该控件中获得像样的空处理功能似乎更糟糕。我很想看到一个工作示例,说明你们认为是一个用户友好的代码示例,其中包含接受空输入的 std MS 或 Telerik DateTimePicker 控件。

我研究过一些开源控件,但每次他们解决一个问题时,都会引入其​​他问题。

编辑:

请参阅下面我的答案。它似乎工作得很好,现在我只想让它成为每个 DateTimePicker 行为的一部分。

I want to be able to accept a NULL date using the DateTimePicker control.

The "Checked" property appears to be intended to specify whether the control "holds a date" or now. However, when "unchecked", the date still appears, though it appears disabled. To me, this is distracting. If the intent of the unchecked checkbox is to indicate that there is no date value, why is there ANY date value disable or otherwise that appears in the textbox? It seems to me that if the control is unchecked, the textbox should be EMPTY and that seeing a dimmed date value when the user really wants "no value" is distracting.

If the user toggled the checkbox on, then I would like the ability to place a default value into the textbox.

I am considering creating a usercontrol that toggles between a dateTimePicker control and a textBox, but I hate to go through this trouble.

I tried looking a Telerik's DateTimePicker but trying to get decent null handling functionality out of that control seems worse. I'd love to see a working example of what one of you think is a user-friendly code example with either the std MS or Telerik DateTimePicker control that accepts null input.

I've looked at a few opensource controls, but every time they fix one issue, they introduce others.

EDIT:

See my answer below. It seems to work fine, now I just want to make it part of every DateTimePicker's behavior.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

征棹 2024-10-13 21:35:16

我也有同样的问题。好吧,实际上我很聪明,可以理解,但我的用户遇到了问题。

我通过删除复选框并添加 2 个单选按钮来解决。现在看起来像这样:(

使用伪 UI)

O No value entered
O | 1/1/2010   |V|

当没有值(空)时检查顶部单选按钮,当有值时检查底部单选按钮。我没有隐藏或禁用底部控件,用户似乎也明白。

缺点是,它需要更多的空间。

PS:用户接下来会抱怨的是当组合框具有焦点时使用滚轮。

I had the same problem. Well, actually I'm smart enough to understand, but my users had a problem.

I solved by removing the checkbox, and adding 2 radio buttons. Looks something like this now:

(using pseudo UI)

O No value entered
O | 1/1/2010   |V|

The top radiobutton is checked when there is no value (null), the bottom one when there is a value. I do not hide, or disable the bottom control, and users seem to understand.

The downside is, that it takes a lot more space.

PS: Next thing users will complain about is using the scroll-wheel when a combo-box has focus.

飘落散花 2024-10-13 21:35:16

Klugey,但它似乎完成了工作。如果未选中该复选框,则假定为 NULL 值。

Private Sub DateTimePicker1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged


    If DateTimePicker1.Checked Then
        DateTimePicker1.Format = DateTimePickerFormat.Short 'Or whatever the original format was
    Else
        DateTimePicker1.Format = DateTimePickerFormat.Custom
        DateTimePicker1.CustomFormat = " "
    End If

End Sub

好的,下一个问题...如何将此行为滚动到子类 DateTimePicker 中?我想要做的是捕获“属性”窗口中设置的 Format 和 CustomFormat 属性的原始值。但是,这显然不是这样做的方法。

这是我微弱的尝试:

Public Class NullableDateTimePicker

    Inherits DateTimePicker

    Private _OriginalFormat As DateTimePickerFormat
    Private _OriginalCustomerFormat As String

    Private Sub NullableDateTimePicker_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ValueChanged

        If Me.Checked Then
            Me.Format = _OriginalFormat
            Me.CustomFormat = _OriginalCustomerFormat
        Else
            Me.Format = DateTimePickerFormat.Custom
            Me.CustomFormat = " "
        End If
    End Sub

    Private Sub _DP_FormatChanged(ByVal sender As Object, ByVal e As System.EventArgs)

        Static Count As Integer

        If Count = 0 Then
            _OriginalFormat = Me.Format
            _OriginalCustomerFormat = Me.CustomFormat
        End If

        Count += 1

    End Sub

    Public Sub New()
        AddHandler MyBase.FormatChanged, AddressOf _DP_FormatChanged
    End Sub
End Class

Klugey, but it seems to get the job done. If the checkbox is not checked, assume a NULL value.

Private Sub DateTimePicker1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged


    If DateTimePicker1.Checked Then
        DateTimePicker1.Format = DateTimePickerFormat.Short 'Or whatever the original format was
    Else
        DateTimePicker1.Format = DateTimePickerFormat.Custom
        DateTimePicker1.CustomFormat = " "
    End If

End Sub

OK, the next question...How do I roll this behavior into a subclassed DateTimePicker? What I want to do is to capture the original values of the Format and CustomFormat properties as set in the Properties window. But, this clearly isn't the way to do it.

Here's my feeble attempt:

Public Class NullableDateTimePicker

    Inherits DateTimePicker

    Private _OriginalFormat As DateTimePickerFormat
    Private _OriginalCustomerFormat As String

    Private Sub NullableDateTimePicker_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ValueChanged

        If Me.Checked Then
            Me.Format = _OriginalFormat
            Me.CustomFormat = _OriginalCustomerFormat
        Else
            Me.Format = DateTimePickerFormat.Custom
            Me.CustomFormat = " "
        End If
    End Sub

    Private Sub _DP_FormatChanged(ByVal sender As Object, ByVal e As System.EventArgs)

        Static Count As Integer

        If Count = 0 Then
            _OriginalFormat = Me.Format
            _OriginalCustomerFormat = Me.CustomFormat
        End If

        Count += 1

    End Sub

    Public Sub New()
        AddHandler MyBase.FormatChanged, AddressOf _DP_FormatChanged
    End Sub
End Class
蓝咒 2024-10-13 21:35:16

我意识到这已经是你最初的问题很多年之后的事了,但这里有一个 Telerik RadDateTimePicker 的子类,它可以满足你的要求:

Imports Telerik.WinControls.UI

Public Class DateTimePickerWithNull
    Inherits Telerik.WinControls.UI.RadDateTimePicker

    Private ReadOnly _calendar As RadCalendar

    Sub New()
        Dim calendarBehavior As RadDateTimePickerCalendar = Me.DateTimePickerElement.GetCurrentBehavior()
        calendarBehavior.DropDownMinSize = New Size(220, 150)

        _calendar = calendarBehavior.Calendar
        _calendar.ShowFooter = True

        AddHandler _calendar.ClearButton.Click, AddressOf ClearButton_Click
        AddHandler _calendar.TodayButton.Click, AddressOf TodayButton_Click
    End Sub

    Private Sub ClearButton_Click(sender As Object, e As EventArgs)
        'Do this to put the calendar away
        _calendar.SelectedDate = _calendar.FocusedDate

        'Then clear
        Me.SetToNullValue()
    End Sub

    Private Sub TodayButton_Click(sender As Object, e As EventArgs)
        _calendar.SelectedDate = _calendar.FocusedDate
    End Sub

End Class

要获取选择器的值:

If DateTimePicker1.Value.Date = DateTimePicker1.NullDate Then
    Label1.Text = "Null"
Else
    Label1.Text = DateTimePicker1.Value.ToLongDateString
End If

I realise this is many years after your initial question but here's a subclass of the Telerik RadDateTimePicker that does what you were asking for:

Imports Telerik.WinControls.UI

Public Class DateTimePickerWithNull
    Inherits Telerik.WinControls.UI.RadDateTimePicker

    Private ReadOnly _calendar As RadCalendar

    Sub New()
        Dim calendarBehavior As RadDateTimePickerCalendar = Me.DateTimePickerElement.GetCurrentBehavior()
        calendarBehavior.DropDownMinSize = New Size(220, 150)

        _calendar = calendarBehavior.Calendar
        _calendar.ShowFooter = True

        AddHandler _calendar.ClearButton.Click, AddressOf ClearButton_Click
        AddHandler _calendar.TodayButton.Click, AddressOf TodayButton_Click
    End Sub

    Private Sub ClearButton_Click(sender As Object, e As EventArgs)
        'Do this to put the calendar away
        _calendar.SelectedDate = _calendar.FocusedDate

        'Then clear
        Me.SetToNullValue()
    End Sub

    Private Sub TodayButton_Click(sender As Object, e As EventArgs)
        _calendar.SelectedDate = _calendar.FocusedDate
    End Sub

End Class

To get the value of the picker:

If DateTimePicker1.Value.Date = DateTimePicker1.NullDate Then
    Label1.Text = "Null"
Else
    Label1.Text = DateTimePicker1.Value.ToLongDateString
End If
不一样的天空 2024-10-13 21:35:16

想要正确有点棘手。这看起来不错:

Imports System.ComponentModel

Public Class MyDateTimePicker
    Inherits DateTimePicker
    Implements ISupportInitialize

    Public Sub New()
        Me.ShowCheckBox = True
        Me.NullDate = True
    End Sub

    Private CustomFormatBacking As String = ""
    Private FormatBacking As DateTimePickerFormat = DateTimePickerFormat.Long

    <DefaultValue(True)> _
    <Bindable(True)> _
    Public Property NullDate() As Boolean
        Get
            Return Not Me.Checked
        End Get
        Set(ByVal value As Boolean)
            Me.Checked = Not value
        End Set
    End Property

    <DefaultValue("")> _
    <Localizable(True)> _
    <RefreshProperties(RefreshProperties.Repaint)> _
    Public Shadows Property CustomFormat() As String
        Get
            Return CustomFormatBacking
        End Get
        Set(ByVal value As String)
            CustomFormatBacking = value
            If DesignMode Or Not NullDate Then MyBase.CustomFormat = value
        End Set
    End Property

    <RefreshProperties(RefreshProperties.Repaint)> _
    Public Shadows Property Format() As DateTimePickerFormat
        Get
            Return FormatBacking
        End Get
        Set(ByVal value As DateTimePickerFormat)
            FormatBacking = value
            If DesignMode Or Not NullDate Then MyBase.Format = value
        End Set
    End Property

    <DefaultValue(true)> _
    <Bindable(True)> _
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
    Public Shadows Property Checked() As Boolean
        Get
            Return MyBase.Checked
        End Get
        Set(ByVal value As Boolean)
            MyBase.Checked = value
        End Set
    End Property

    Private Sub updateNullState()
        If NullDate and Not DesignMode Then
            MyBase.CustomFormat = " "
            MyBase.Format = DateTimePickerFormat.Custom
        Else
            MyBase.CustomFormat = CustomFormatBacking
            MyBase.Format = FormatBacking
        End If
    End Sub

    Public Sub BeginInit() Implements System.ComponentModel.ISupportInitialize.BeginInit
    End Sub

    Public Sub EndInit() Implements System.ComponentModel.ISupportInitialize.EndInit
        updateNullState()
    End Sub

    Protected Overrides Sub OnValueChanged(ByVal eventargs As System.EventArgs)
        MyBase.OnValueChanged(eventargs)
        updateNullState()
    End Sub

End Class

A bit tricky to get right. This looked good:

Imports System.ComponentModel

Public Class MyDateTimePicker
    Inherits DateTimePicker
    Implements ISupportInitialize

    Public Sub New()
        Me.ShowCheckBox = True
        Me.NullDate = True
    End Sub

    Private CustomFormatBacking As String = ""
    Private FormatBacking As DateTimePickerFormat = DateTimePickerFormat.Long

    <DefaultValue(True)> _
    <Bindable(True)> _
    Public Property NullDate() As Boolean
        Get
            Return Not Me.Checked
        End Get
        Set(ByVal value As Boolean)
            Me.Checked = Not value
        End Set
    End Property

    <DefaultValue("")> _
    <Localizable(True)> _
    <RefreshProperties(RefreshProperties.Repaint)> _
    Public Shadows Property CustomFormat() As String
        Get
            Return CustomFormatBacking
        End Get
        Set(ByVal value As String)
            CustomFormatBacking = value
            If DesignMode Or Not NullDate Then MyBase.CustomFormat = value
        End Set
    End Property

    <RefreshProperties(RefreshProperties.Repaint)> _
    Public Shadows Property Format() As DateTimePickerFormat
        Get
            Return FormatBacking
        End Get
        Set(ByVal value As DateTimePickerFormat)
            FormatBacking = value
            If DesignMode Or Not NullDate Then MyBase.Format = value
        End Set
    End Property

    <DefaultValue(true)> _
    <Bindable(True)> _
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
    Public Shadows Property Checked() As Boolean
        Get
            Return MyBase.Checked
        End Get
        Set(ByVal value As Boolean)
            MyBase.Checked = value
        End Set
    End Property

    Private Sub updateNullState()
        If NullDate and Not DesignMode Then
            MyBase.CustomFormat = " "
            MyBase.Format = DateTimePickerFormat.Custom
        Else
            MyBase.CustomFormat = CustomFormatBacking
            MyBase.Format = FormatBacking
        End If
    End Sub

    Public Sub BeginInit() Implements System.ComponentModel.ISupportInitialize.BeginInit
    End Sub

    Public Sub EndInit() Implements System.ComponentModel.ISupportInitialize.EndInit
        updateNullState()
    End Sub

    Protected Overrides Sub OnValueChanged(ByVal eventargs As System.EventArgs)
        MyBase.OnValueChanged(eventargs)
        updateNullState()
    End Sub

End Class
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文