我正在使用
DatePicker
在 WPF 中构建自定义 UserControl
。我的控件里面有 3 个文本框,负责根据文化信息指示日、月和年。
我试图将焦点从一个文本框移动到另一个文本框以简化数据输入,但我总是遇到同样的问题,焦点移动但总是最终到达控件内 3 个文本框中的第一个。
以下是 TextChanged 事件的代码,该事件适用于所有三个文本框:
private void _DateTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
EvolutionTextbox textBox = sender as EvolutionTextbox;
string tagText = textBox.TagText.ToString();
int value;
bool emptyText = false;
bool isNumber = Int32.TryParse(textBox.InputText, out value);
if (textBox.InputText == "") {
emptyText = true;
}
_UnregisterEvents();
int year = 2024; // default value for year
int month = 1; // default value for month
int day = 1; // default value for day
// get current input from textboxes
if (_YearTextBox.InputText != "" && _YearTextBox.InputText.Count() == 4) {
year = Int32.Parse(_YearTextBox.InputText);
}
if (_MonthTextBox.InputText != "" && Int32.Parse(_MonthTextBox.InputText) < 12 && Int32.Parse(_MonthTextBox.InputText) > 0) {
month = Int32.Parse(_MonthTextBox.InputText);
}
if (_DayTextBox.InputText != "") {
day = Int32.Parse(_DayTextBox.InputText);
}
int maxDay = DateTime.DaysInMonth(year, month);
switch (tagText) {
case "d": // Day
if (value <= 0 || value > maxDay) {
((EvolutionTextbox)sender).InputText = maxDay.ToString();
}
break;
case "M": // Month
if (value <= 0 || value > 12) {
((EvolutionTextbox)sender).InputText = "12";
}
else if (value <= 12) {
maxDay = DateTime.DaysInMonth(year, value);
if (day > maxDay) {
_DayTextBox.InputText = maxDay.ToString();
}
}
break;
case "yyyy": // Year
if (value <= 0 || value > 9999) {
((EvolutionTextbox)sender).InputText = "9999";
}
else if (value > 0) {
maxDay = DateTime.DaysInMonth(value, month);
if (day > maxDay) {
_DayTextBox.InputText = maxDay.ToString();
}
}
break;
}
// If empty set empty string
if (emptyText) {
((EvolutionTextbox)sender).InputText = "";
}
_RegisterEvents();
//jump between textboxes
if ((tagText == "d" || tagText == "M") && textBox.InputText.Length == 2) {
TraversalRequest req = new TraversalRequest(FocusNavigationDirection.Next);
MoveFocus(req);
}
else if (tagText == "yyyy" && textBox.InputText.Length == 4) {
TraversalRequest req = new TraversalRequest(FocusNavigationDirection.Next);
MoveFocus(req);
}
}
我也尝试过放
KeyboardNavigation.TabNavigation="Contained"
和KeyboardNavigation.TabNavigation="Local"
,但它们没有达到预期的效果。我还尝试通过为各个控件设置 TabIndex = 1,2,3 来设置各种控件的 TabIndex
。
我不明白可能缺少什么或我做错了什么!
您观察到的行为是正确的:您总是在父级
FrameworkElement.MoveFocus
上调用UserControl
以将焦点移动到下一个元素。层次结构中的下一个元素是第一个 TextBox
。除非您移动子元素树内的元素,否则相对于 MoveFocus
调用者的下一个元素将永远不会改变。
您必须对当前聚焦的元素调用
MoveFocus
才能继续焦点遍历。
假设您对参与的
_DateTextBox_TextChanged
元素的所有 TextBox.TextChanged
事件使用相同的 TextBox
事件处理程序,那么您必须按如下方式更改焦点导航部分:
private void _DateTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
...
//jump between textboxes
bool isInputDayOrMonth = tagText == "d" || tagText == "M";
int expectedInputLength = isInputDayOrMonth ? 2 : 4;
if (textBox.InputText.Length == expectedInputLength)
{
TraversalRequest req = new TraversalRequest(FocusNavigationDirection.Next);
//MoveFocus(req);
textBox.MoveFocus(req);
}
}