设置默认键盘焦点加载UserControl

时间:2012-03-02 15:23:03

标签: wpf

我有一个MVVM设置,主窗口包含一个ContentControl。 我将其设置为特定的视图模型,然后映射到视图。 视图是用户控件。 我希望能够在加载时将默认键盘焦点设置为usercontrol(View)中的默认元素,这样最终只需使用向上,向下,向左,向右和输入即可驱动应用程序。 我的一些失败尝试是设置

FocusManager.FocusedElement="{Binding ElementName=DefaultElement}"

在我的内容控件标记中。这设置了逻辑焦点,但不设置键盘焦点

如果可能的话,我宁愿将解决方案保留在xaml中,但尝试将以下内容放在代码中。

Keyboard.Focus(DefaultElement);  

这不起作用但如果我首先弹出一个消息框就行了。我为什么会有点困惑。

MessageBox.Show(Keyboard.FocusedElement.ToString());
Keyboard.Focus(DefaultElement);

EDIT :::: 我把它放在我的用户控件的onloaded事件中。它似乎有效但任何人都可以看到任何可能在这个优先级别上出现的问题。 I.E该行为永远不会发生的情况?

Dispatcher.BeginInvoke(
            DispatcherPriority.ContextIdle,
            new Action(delegate()
                {
                    Keyboard.Focus(DefaultElement);
                }));

3 个答案:

答案 0 :(得分:25)

似乎这个必须根据具体情况实施变通方法。对我来说似乎效果最好的解决方案是在更改OnVisible时将焦点代码插入调度程序中。这不仅在View / Usercontrol加载时设置焦点,而且如果您通过Visibility更改Views也是如此。如果您隐藏然后显示映射到ViewModel的ContentControl,那么Loaded事件将不会触发,您将被强制进入鼠标输入或Tabbing(如果您想使用遥控器导航您的应用程序则不太好) 。 然而,VisibilityChanged总会开火。这就是我为列表框最终得到的结果。

private void ItemsFlowListBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue == true)
        {
            Dispatcher.BeginInvoke(
            DispatcherPriority.ContextIdle,
            new Action(delegate()
            {
                ItemsFlowListBox.Focus();
                ItemsFlowListBox.ScrollIntoView(ItemsFlowListBox.SelectedItem);
            }));
        }
    }

答案 1 :(得分:1)

我在Winforms应用程序中托管的WPF UserControl具有相同的症状。只是想注意当我在Winforms应用程序中找到一个正常的TabIndex修复它时,我正要尝试这个解决方案

How to set which control has focus on Application start

"具有最小选项卡索引的选项会自动获得焦点(假设TabStop属性设置为true)。只需适当设置标签索引。

答案 2 :(得分:0)

这是一个棘手的问题,没有简单的答案。我现在正在这样做,虽然我不确定我喜欢它:

    public MyView()
    {
        InitializeComponent();

        // When DataContext changes hook the txtName.TextChanged event so we can give it initial focus
        DataContextChanged +=
            (sender, args) =>
                {
                    txtName.TextChanged += OnTxtNameOnTextChanged;
                };
    }

    private void OnTxtNameOnTextChanged(object o, TextChangedEventArgs eventArgs)
    {
        // Setting focus will select all text in the TextBox due to the global class handler on TextBox
        txtName.Focus();
        // Now unhook the event handler, since it's no longer required
        txtName.TextChanged -= OnTxtNameOnTextChanged;
    }

如果您想知道全局类处理程序的作用,那就是:

    protected override void OnStartup(StartupEventArgs e)
    {
        ...

        // Register a global handler for this app-domain to select all text in a textBox when
        // the textBox receives keyboard focus.
        EventManager.RegisterClassHandler(
            typeof (TextBox), UIElement.GotKeyboardFocusEvent,
            new RoutedEventHandler((sender, args) => ((TextBox) sender).SelectAll()));

在接收键盘焦点时自动选择TextBox文本。