WPF:在ItemsControl中按Enter键从一个单元格移动到下一个单元格

时间:2017-06-29 13:12:19

标签: c# wpf xaml data-entry

我的WPF控件定义如下:

        <ItemsControl ItemsSource="{Binding DutyValueBinders}" IsEnabled="{Binding Enabled}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Value, TargetNullValue=''}"  Width="50"></TextBox>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

这会生成一个网格,如下所示:

Grid with data

因此,尽管XAML中只定义了一个文本框,但用户会看到一个网格。

我想要做的是,在用户输入一个值并按Enter或Return后,焦点应传递到下一个单元格,依此类推,直到到达网格末尾。我尝试将此例程放入后面的代码中(从Stackoverflow上的另一个线程复制):

    private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter || (!e.IsToggled && sender is Button)) return;
        var request = new TraversalRequest(FocusNavigationDirection.Next);
        var keyboardFocus = Keyboard.FocusedElement as UIElement;

        if (keyboardFocus == null) return;
        keyboardFocus.MoveFocus(request);
        e.Handled = true;
    }

并修改了XAML的标题,如下所示:

<UserControl ...
             (Other references)
             ... 
             d:DesignHeight="300" d:DesignWidth="300" PreviewKeyDown="UserControl_PreviewKeyDown">

麻烦的是,由于XAML定义中只有一个文本框,因此没有tabindex顺序,因此按Enter键时光标就会消失。

有没有办法做到这一点,没有完全废弃XAML并重新开始使用不同类型的控件?

1 个答案:

答案 0 :(得分:1)

如此处理PreviewKeyDown的{​​{1}}事件怎么样?:

ItemsControl
<ItemsControl ItemsSource="{Binding DutyValueBinders}" IsEnabled="{Binding Enabled}"
              PreviewKeyDown="ItemsControl_PreviewKeyDown">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Value, TargetNullValue=''}"  Width="50"></TextBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>