简体   繁体   English

用户控制失去键盘焦点

[英]user control loses keyboard focus

I made a user control, which I called InputTextBox, that present text which the user can edit only after clicking the control: 我创建了一个用户控件,我称之为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>

When the user click the button the following callack is used: 当用户单击该按钮时,使用以下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);
    }

There are two more important events that are handled within the control. 在控件中处理两个更重要的事件。 The first is when the control loses keyboard focus: 第一个是控件失去键盘焦点时:

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

And the other is when the user presses the TAB or ENTER keys: 另一种是当用户按下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);
        }
    }

This raises a simple routed event I registered for this control called KeyExit. 这引发了我为此控件注册的名为KeyExit的简单路由事件。

So, basically, it's like this control has two "modes": "edit mode" which the user can activate by simply clicking on the control, and "view mode", which the user can return to by giving any other control in the UI keyboard focus. 所以,基本上,就像这个控件有两个“模式”:用户可以通过简单地点击控件来激活的“编辑模式”,以及用户可以通过在UI中提供任何其他控件来返回的“查看模式”键盘焦点。

In my UI I have a stack panel with a bunch of these controls in it - each one is wrapped inside a class I created that is similar in concept to ListViewItem. 在我的UI中,我有一个堆栈面板,其中包含一堆这些控件 - 每个控件都包含在我创建的类中,与ListViewItem的概念类似。 The idea is that when the user is in edit mode inside one of the items in the stack panel and click the TAB or ENTER key, the next control in the panel will get into edit mode. 这个想法是当用户在堆栈面板中的一个项目内处于编辑模式并单击TAB或ENTER键时,面板中的下一个控件将进入编辑模式。

So, I have the following event callback: 所以,我有以下事件回调:

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();
                    }
                }

            }
        }
    }

Everything is called properly, but immediately after all of it is done, the previous item, which I tabbed out of, gets the keyboard focus back and cause no item in the stack to be in edit mode. 所有内容都被正确调用,但是在完成所有操作之后,上一个项目(我选中)将使键盘焦点恢复,并且不会导致堆栈中的任何项目处于编辑模式。 So, if, for example, the first item in the stack was in edit mode, once the user hit the tab key, the second item in the stack gets into edit mode, but then the first item gets keyboard focus back immediately. 因此,例如,如果堆栈中的第一个项目处于编辑模式,一旦用户点击Tab键,堆栈中的第二个项目就会进入编辑模式,但第一个项目会立即获得键盘焦点。 Can anybody understand why this is happening? 任何人都能理解为什么会这样吗?

StackPanel Focusable is false by default. StackPanel默认情况下,Focusable为false。 Suggest ensure it's true. 建议确保它是真的。

Also for checking indeces, one generally wants the index to be < count. 另外,对于检查indeces,通常希望索引为<count。 So your index + 1 could == count if it's == count - 1. Don't you want: 所以你的索引+ 1可以==计算它是否= =计数 - 1.你不想要:

if (itemIndex < ...Count - 1)
That way, item index + 1 will always be <= Count - 1 ? 那样,项目索引+ 1将始终<=计数 - 1?

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

Also you can use box.Focus() instead of Keyboard.Focus(box) but that may not be necessary. 您也可以使用box.Focus()而不是Keyboard.Focus(box)但这可能没有必要。

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

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