如何将DateTimePicker设置为只读?

14

我有一个DateTimePicker(可为空版本),需要它是只读的。如果将其禁用,我对其显示不满意,想知道是否有人有如何停止字段更新的巧妙示例?

谢谢。

15个回答

14

我知道这篇文章很老,但是如果有其他人在搜索时需要帮助(因为我第一次通过谷歌找到它),你可以使用以下方法:

this.dateTimePicker1.Enabled = false;

使其表现与文本框相同,就像使用this.textbox1.ReadOnly = true时一样。


2
我总是会忽略掉一些简单的解决方案,这次也不例外。但这个方法对我的情况非常有效。唯一不那么理想的情况是,如果你不喜欢灰色的外观,而这种外观在 ReadOnly = true 中是不存在的。 - Broots Waymb
2
启用并不等同于只读。当文本框为只读时,您仍然可以单击它,移动插入符号,选择文本并复制它。 - Robin Bennett

10

你可以挂接Changed事件,如果值有改变就将其设置回所需的值(如果不同的话)-这样你就可以覆盖任何通过鼠标或键盘引起的更改。

你是否考虑过使用不同的控件,例如只读文本框或甚至标签控件?


这会导致一个看起来可编辑的框,但当你离开日期选择器时,值会改回旧值。 - Robin Bennett

3

这个问题——六年后——似乎仍然引起了一些关注,所以我会分享我的两分钱:对我来说有效的方法是1)创建一个UserControl并将基类更改为DateTimePicker 2)每当值发生变化时,拍摄控件的一个小位图快照 3)拦截WM_PAINT消息,并且如果我们的控件被禁用,则绘制位图而不是控件。 (注意:designer.cs中的AutoScaleMode属性会导致编译错误,所以只需删除即可)。

public partial class DateTimePickerWithReadOnly : DateTimePicker
{
  Bitmap ReadOnlyImage;
  // We maintain a "shadow" control to avoid capturing selections in the snapshot.
  // If you use different formatting or styles just make sure the shadow is set to match!
  DateTimePicker Shadow = new DateTimePicker(); 
  public DateTimePickerWithReadOnly()
  {
    InitializeComponent(); 
    CaptureBitmap();
    this.ValueChanged += new EventHandler(DateTimePickerWithReadOnly_ValueChanged);
  }
  private void CaptureBitmap()
  {
    Shadow.Value = Value;
    Shadow.Size = Size;
    ReadOnlyImage = new Bitmap(Width, Height);
    Shadow.DrawToBitmap(ReadOnlyImage, new Rectangle(0, 0, Size.Width, Size.Height));
  }
  void DateTimePickerWithReadOnly_ValueChanged(object sender, EventArgs e)
  {
    CaptureBitmap();
  }
  protected override void DefWndProc(ref Message m)
  {
    base.DefWndProc(ref m);
    // WM_PAINT is 0x000F
    if ((m.Msg == 0x000F) && !Enabled)
    {
      Graphics g = base.CreateGraphics();
      g.DrawImage(ReadOnlyImage, new Rectangle(0, 0, Size.Width, Size.Height));
      g.Dispose();
    }
  }
}

2
作为另一个建议:使用文字框(或标签)并将其设置为只读。显示您想要的值。
如果必须使用日期时间选择器,请创建一个日期时间选择器和一个文本框。将它们重叠在一起。当您需要日期时间选择器时,隐藏文本框。等等。

2

在按下键盘时:e.SuppressKeyPress = true; 对我有用,我仍然可以选择日期,但无法手动输入


1

我曾经采用的一种方法是将可允许的日期范围限制为单个值。

dateTimePicker.MinDate = dateTimePicker.Value;
dateTimePicker.MaxDate = dateTimePicker.Value;

1
“如果它被禁用,我对显示不满意。”为什么?如果是因为禁用的文本框看起来很奇怪,您可以更改禁用样式使其看起来正常,或以更漂亮的方式指示它只通过日期选择器接受输入。可能没有边框,以表明它不是真正的文本框。”

请问您能指出那个属性是哪个吗?我原本以为在winforms中无法更改禁用样式,但如果可以的话,我很想尝试一下。非常感谢。 - Guillermo Gutiérrez
抱歉...现在已经过去四年了,我完全不记得这个答案或者我当时在说什么了 :( - Sudhir Jonathan

1
我知道这已经过时了,但我讨厌发现仍然存在没有解决方案的问题。顺便说一下,您可能不想禁用它的原因是您无法轻松显示工具提示和自定义背景颜色(尽管可以更容易地解决此问题)
无论如何,我找到了解决方法(感谢其他人在这里的帮助),我相信这正是问题所在。我已经为DateTimePicker添加了自定义控件。
然后我添加了一个只读属性。我的问题出现在VB.Net项目中
如果Readonly = True,请覆盖KeyDown事件并将其标记为已处理。
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
  If mReadOnly Then
    e.Handled = True
  Else
    MyBase.OnKeyDown(e)
  End If
End Sub

这段代码处理了箭头键和 F4 下拉键。要禁用下拉框,需要重写 WndProc 方法:
Protected Overrides Sub WndProc(ByRef m As Message)
  '   m.Msg = 0x201 / &H201 = WM_LBUTTONDOWN
  '   m.Msg = 0x203 / &H203 = WM_LBUTTONDBLCLK
  If ReadOnly And (m.Msg = &H201 Or m.Msg = &H203) Then
    Return
  End If
  MyBase.WndProc(m)
End Sub

为了在我的OnPaint重载中使它看起来是只读的,我有以下代码:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

Dim g As Graphics = Me.CreateGraphics()

Dim dropDownIcon As Rectangle = New Rectangle(ClientRectangle.Width - 17, 0, 17, ClientRectangle.Height)
Dim b As Brush
Dim v As VisualStyles.ComboBoxState
Dim vn As ButtonState

b = New SolidBrush(Me.BackColor)

If Me.IsReadOnly Then
  v = VisualStyles.ComboBoxState.Disabled
  vn = ButtonState.Inactive
Else
  b = New SolidBrush(Me.BackColor)
    v = VisualStyles.ComboBoxState.Normal
    vn = ButtonState.Normal
  End If

'changed to only do this if the control is visible
If Me.Visible = True Then

  'colour rectangle
  g.FillRectangle(b, 0, 0, ClientRectangle.Width, ClientRectangle.Height)

  'for border 
  g.DrawRectangle(System.Drawing.SystemPens.ActiveBorder, 0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1)

  'for text
  g.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), 0, 2)


  'we need to render the dropdown when visual styles is not turned on
  If ComboBoxRenderer.IsSupported Then
    ComboBoxRenderer.DrawDropDownButton(g, dropDownIcon, v)
  Else
    ControlPaint.DrawComboButton(g, dropDownIcon, vn)
  End If
End If

g.Dispose()
b.Dispose()
End Sub

0
这不是最好的做法,但可以阻止datetime在keyUp时更新。
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    }

    private DateTime originalValue;

    private void dateTimePicker1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        originalValue = dateTimePicker1.Value;
    }

    private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
    {
        dateTimePicker1.Value = originalValue;
    }
}

0
  1. 首先,我们必须记住原始日期时间。

    procedure TForm1.dtpDateEnter(Sender: TObject);
    begin
      oldDtpDate := dtpDate.DateTime;
    end;
    
  2. 在TForm1.dtpDateClick(Sender: TObject)过程中: begin dtpDate.DateTime := oldDtpDate; end;

    procedure TForm1.dtpDateExit(Sender: TObject);
    begin
      dtpDate.DateTime :=  oldDtpDate;
    end;
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接