UserControl 中的 MoveFocus()

问题描述 投票:0回答:1

我正在使用

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
。 我不明白可能缺少什么或我做错了什么!

c# wpf wpf-controls
1个回答
0
投票

您观察到的行为是正确的:您总是在父级

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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.