C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?
Posted
技术标签:
【中文标题】C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?【英文标题】:C# Windows Forms DateTimePicker, how to get the SelectedText, SelectionStart, and SelectionLength? 【发布时间】:2020-08-12 23:31:22 【问题描述】:.NET DateTimePicker 有文本,但我不知道如何获取和设置 DateTimePicker 的 SelectionStart、SelectionLength 和 SelectionText 属性。
例如,我如何以编程方式选择日期“2001 年 11 月 17 日”中的 2 天数字? 以及如何以编程方式确定当前选择的起始位置?
基本上,我想做的是类似于以下代码:
// Select the day's text
((TextBox)myDateTimePicker).SelectionStart = 3;
((TextBox)myDateTimePicker).SelectionLength = 2;
// Get the text start position
return ((TextBox)myDateTimePicker).SelectionStart;
【问题讨论】:
在DTP.Enter
事件中调用SendKeys.Send("Right")
以选择下一部分。
@JQSOFT 读懂了我的想法。实际上,这是我的最终目标。当按下空格键时,我会执行您描述的部分步进。我希望 Tab 也可以用于步进。不幸的是,Tab 然后在文本框中卡住。我想知道 SelectionStart 何时位于最后或第一部分(因此我可以在 year 中为 Tab 设置 PreviewKeyDown 的 e.IsInputKey = false;
并在 month 中设置 Shift-Tab 所以用户可以 Tab 浏览 DTP 部分并继续前进。
我还希望在从 DTP 左侧从外部控件输入 DTP 时能够选择 DTP 的月份;或从 DTP 右侧的外部控件输入 DTP 时选择 DTP 的 年份。
绝招here。
@JQSOFT 的妙招对我有用。
【参考方案1】:
以下代码是我的问题的答案。它源自DateTimePicker get focused field 问题的answer。
public event System.EventHandler<EventArgs> Parent_ValueChanged;
public enum DatePart
YEAR,
MONTH,
DAY
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DatePart SelectedPart get; set;
private DateTime m_PreviousValue = TimeTools.UnixBaseTime;
private bool m_CheckSelectedPart = false;
public void DateTimeField_GotFocus(object sender, EventArgs e)
m_PreviousValue = this.Value;
m_CheckSelectedPart = true;
SendKeys.SendWait("UP");
SendKeys.SendWait("DOWN");
m_CheckSelectedPart = false;
public void DateTimeField_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
switch (e.KeyCode)
case Keys.Space:
e.IsInputKey = true;
break;
case Keys.Tab:
m_PreviousValue = this.Value;
m_CheckSelectedPart = true;
SendKeys.SendWait("UP");
SendKeys.SendWait("DOWN");
m_CheckSelectedPart = false;
// Set e.IsInputKey to false to let Windows use the Tab
// to go to the previous or next component with TabStop = true
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
// false = exit to the left or up
e.IsInputKey = !(SelectedPart == DatePart.MONTH);
else
// false = exit to the right or down
e.IsInputKey = !(SelectedPart == DatePart.YEAR);
break;
default: break;
public void DateTimeField_KeyDown(object sender, KeyEventArgs e)
// Mimic Delphi's DateTimePicker behavior by advancing to the next part in the format
// using Space or Tab
if (e.KeyCode.Equals(Keys.Space) || e.KeyCode.Equals(Keys.Tab))
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
SendKeys.Send("left");
else
SendKeys.Send("right");
private void DateTimeField_ValueChanged(object sender, EventArgs e)
if ((m_CheckSelectedPart) && (sender is DateTimePicker dtp))
TimeSpan change = (dtp.Value - m_PreviousValue);
var dayChange = Math.Abs(change.Days);
if (dayChange == 1)
SelectedPart = DatePart.DAY;
else if (dayChange >= 365)
SelectedPart = DatePart.YEAR;
else
SelectedPart = DatePart.MONTH;
m_PreviousValue = dtp.Value;
// parent's ValueChanged event handler
Parent_ValueChanged?.Invoke(sender, e);
【讨论】:
【参考方案2】:我知道这个问题被问了很长时间,但它对于下一个仍在寻找暂时未解决的解决方案的人很有用,再次询问应该是一个满足的解决方案,编写的代码更少,并且管理。
在焦点离开DateTimerPicker
控件并稍后返回到它之后,控件会记住哪个部分(日、月或年)具有焦点。焦点回到那部分。
如何强制焦点回到控件的第一个per?
要强制控件忘记哪个部分具有焦点,您可以更改格式,然后再次将其更改回来。因此,如果将其设置为 Short,请将其设置为 Long,然后再设置为 Short。
诀窍是在通过 Enter 事件返回焦点后执行此操作
所以最好的地方是在 Enter 事件中:
Private Sub DateTimePicker_Enter(sender As Object, e As System.EventArgs) Handles DateTimePicker.Enter
DateTimePicker.Format = DateTimePickerFormat.Long
DateTimePicker.Format = DateTimePickerFormat.Short
End Sub
【讨论】:
以上是关于C# Windows 窗体 DateTimePicker,如何获取 SelectedText、SelectionStart 和 SelectionLength?的主要内容,如果未能解决你的问题,请参考以下文章
c#中让Windows窗体只运行一次,并在第二次启动窗体时激活该窗体