【问题标题】:How do you set a DateTimePicker to be read only?如何将 DateTimePicker 设置为只读?
【发布时间】:2009-03-18 12:07:13
【问题描述】:

我有一个 DateTimePicker(可空版本),我需要只读。如果它被禁用,我对显示不满意,所以想知道是否有人有一个很好的例子来说明如何停止现场更新?

谢谢。

【问题讨论】:

    标签: c# winforms .net-2.0


    【解决方案1】:

    我知道这已经很老了,但为了帮助其他人搜索这个(因为这是我通过谷歌找到的第一个)你可以使用:

    this.dateTimePicker1.Enabled = false;
    

    使其行为方式与 this.textbox1.ReadOnly = true 的文本框相同

    【讨论】:

    • 我完全忽略的简单解决方案(像往常一样)。为我的案子工作。这种解决方案不是那么理想的唯一方法是,如果您不喜欢 ReadOnly = true 所没有的灰色外观。
    • 启用与只读不同。当文本框为只读时,您仍然可以单击它,移动插入符号,选择文本并复制它。
    【解决方案2】:

    您可以挂钩 Changed 事件,并将值设置回您想要的值(如果不同)——这样您就可以覆盖任何更改的原因(通过鼠标或键盘)

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

    【讨论】:

    • 这会导致一个看起来可以编辑的框,但是当您离开日期选择器时,值会变回旧值。
    【解决方案3】:

    这个问题 - 六年后 - 似乎仍然引起了一些兴趣,所以我会投入 2 美分:对我有用的是 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();
        }
      }
    }
    

    【讨论】:

      【解决方案4】:

      作为另一个建议:使用文本框(或标签)并使其只读。在里面显示你想要的值。

      如果您必须有一个日期时间选择器,请同时创建一个日期时间选择器和一个文本框。将它们叠放在一起。当您需要 datetimepicker 时,隐藏文本框。等等。

      【讨论】:

        【解决方案5】:

        在 Keydown 上:e.SuppressKeyPress = true;为我工作,仍然可以选择日期,但无法手动输入

        【讨论】:

          【解决方案6】:

          “如果显示器被禁用,我不满意”

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

          【讨论】:

          • 你能告诉我那是哪个属性吗?我以为我无法更改 winforms 中的禁用样式,但如果可能的话,我愿意。非常感谢。
          • 对不起......现在已经四年多了,我不记得这个答案或我在说什么:(
          【解决方案7】:

          我这样做的一种方法是简单地将允许的日期范围限制为单个值。

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

          【讨论】:

            【解决方案8】:

            我知道它已经过时了,但我讨厌找到仍然相关但没有解决方案的问题。顺便说一句,您可能不想禁用它的原因是您无法轻松显示工具提示和自定义背景色(尽管这可以更轻松地解决)

            无论如何,我找到了我相信问题提出的解决方案(感谢其他地方的其他人)。我已经有了 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
            

            【讨论】:

              【解决方案9】:

              处理 DateTimePicker.MouseClick 事件并将 event.handled 设置为 true

              【讨论】:

              • 您还需要禁用会更改值的键盘输入
              【解决方案10】:

              选择 Changed 事件并设置 e.Cancel = true 怎么样?

              【讨论】:

              • 这行不通。该事件已更改ed。如值已被修改。你不能简单地取消。
              【解决方案11】:

              这不是最好的方法,但这确实会停止通过 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;
                  }
              }
              

              【讨论】:

                【解决方案12】:
                1. 我们首先要记住原来的日期时间。

                  procedure TForm1.dtpDateEnter(Sender: TObject);
                  begin
                    oldDtpDate := dtpDate.DateTime;
                  end;
                  
                2. 过程 TForm1.dtpDateClick(Sender: TObject); 开始 dtpDate.DateTime := oldDtpDate; 结束;

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

                【讨论】:

                  【解决方案13】:
                  this.dateTimePicker1.Enabled = false;
                  

                  这是一种简单而完美的解决方案。

                  【讨论】:

                  • 启用与只读不同。当文本框为只读时,您仍然可以单击它,移动插入符号,选择文本并复制它。
                  【解决方案14】:

                  dateTimePicker2.Enabled = false;

                  【讨论】:

                    【解决方案15】:

                    试试这个:

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

                    【讨论】:

                    • DateTime.Now 不是您希望能够使用的唯一值。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-05-17
                    • 2013-03-30
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多