繁体   English   中英

用户控制失去键盘焦点

[英]user control loses keyboard focus

我创建了一个用户控件,我称之为InputTextBox,它提供了用户只有在单击控件后才能编辑的文本:

<Grid>  
    <TextBox Name="box"
             Text="{Binding RelativeSource={RelativeSource AncestorType=local:InputTextBlock}, Path=Text, Mode=TwoWay}"
             Visibility="Hidden"
             LostKeyboardFocus="box_LostKeyboardFocus"
             KeyDown="box_KeyDown"/>
    <Button Name="block"
            Background="Transparent"
            BorderThickness="0"
            Click="block_Click">
        <Button.Content>
            <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=local:InputTextBlock}, Path=Text}" />
        </Button.Content>
    </Button>
</Grid>

当用户单击该按钮时,使用以下callack:

    private void block_Click(object sender, RoutedEventArgs e)
    {
        StartEdit();
    }

    public void StartEdit()
    {
        box.Visibility = Visibility.Visible;
        block.Visibility = Visibility.Hidden;

        box.CaretIndex = box.Text.Length;

        Keyboard.Focus(box);
    }

在控件中处理两个更重要的事件。 第一个是控件失去键盘焦点时:

private void box_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        box.Visibility = Visibility.Hidden;
        block.Visibility = Visibility.Visible;
    }

另一种是当用户按下TAB或ENTER键时:

private void box_KeyDown(object sender, KeyEventArgs e)
    {
        Key key = e.Key;

        if (key == Key.Enter || key == Key.Tab)
        {
            RoutedEventArgs args = new RoutedEventArgs(KeyExitEvent, this, e.Key);

            RaiseEvent(args);
        }
    }

这引发了我为此控件注册的名为KeyExit的简单路由事件。

所以,基本上,就像这个控件有两个“模式”:用户可以通过简单地点击控件来激活的“编辑模式”,以及用户可以通过在UI中提供任何其他控件来返回的“查看模式”键盘焦点。

在我的UI中,我有一个堆栈面板,其中包含一堆这些控件 - 每个控件都包含在我创建的类中,与ListViewItem的概念类似。 这个想法是当用户在堆栈面板中的一个项目内处于编辑模式并单击TAB或ENTER键时,面板中的下一个控件将进入编辑模式。

所以,我有以下事件回调:

private void item_KeyExit(object sender, RoutedEventArgs e)
    {
        FrameworkElement obj = e.OriginalSource as FrameworkElement;

        if (obj != null)
        {
            var listItem = VisualTreeHelperUtils.FindFirstAncestorOfType<MyListItem>(obj);

            if (listItem != null)
            {
                int itemIndex = stackPanelList.Children.IndexOf(listItem);

                MyListItem nextItem = null;

                if (itemIndex == ucSortableList.Children.Count - 1)
                {
                    nextItem = stackPanelList.Children[itemIndex+1] as MyListItem;
                }

                if (nextItem != null)
                {
                    var item = nextItem.DataContent; // property I made in MyListItem that gives access to the class it wraps

                    InputTextBlock block = item as InputTextBlock;
                    if (block != null)
                    {
                        block.StartEdit();
                    }
                }

            }
        }
    }

所有内容都被正确调用,但是在完成所有操作之后,上一个项目(我选中)将使键盘焦点恢复,并且不会导致堆栈中的任何项目处于编辑模式。 因此,例如,如果堆栈中的第一个项目处于编辑模式,一旦用户点击Tab键,堆栈中的第二个项目就会进入编辑模式,但第一个项目会立即获得键盘焦点。 任何人都能理解为什么会这样吗?

StackPanel默认情况下,Focusable为false。 建议确保它是真的。

另外,对于检查indeces,通常希望索引为<count。 所以你的索引+ 1可以==计算它是否= =计数 - 1.你不想要:

if (itemIndex < ...Count - 1)
那样,项目索引+ 1将始终<=计数 - 1?

if (itemIndex == ucSortableList.Children.Count - 1) { nextItem = stackPanelList.Children[itemIndex+1] as MyListItem; }

您也可以使用box.Focus()而不是Keyboard.Focus(box)但这可能没有必要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM