Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Default Keyboard Focus On Loading A UserControl

Tags:

wpf

I have an MVVM setup with a mainwindow that contains a ContentControl. I set this to a particular viewmodel which then maps to a view. A view is a usercontrol. I want to be able to set the default keyboard focus to a default element in the usercontrol(View) when it loads so the application can eventually be driven just by using up, down, left, right and enter. Some of my failed attempts are setting

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

in my content control tag. This sets the logical focus but not the keyboard focus

I'd rather keep the solution in xaml if possable but have tried placing the following in code behind.

Keyboard.Focus(DefaultElement);  

This does not work but if I popup a message box first it does. I'm a little confused as to why.

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

EDIT:::: I just placed this in my onloaded event of my user control. It seems to work but can anyone see any issues that might arrise at this priority level. I.E a circumstance when the action will never run?

Dispatcher.BeginInvoke(
            DispatcherPriority.ContextIdle,
            new Action(delegate()
                {
                    Keyboard.Focus(DefaultElement);
                }));
like image 355
Oli Avatar asked Mar 02 '12 15:03

Oli


1 Answers

It seems that this wpf the you have to implement a workaround on a case by case basis. The solution that seemed to work best, most of the time for me was to insert the focus code inside the dispatcher when OnVisible was changed. This sets the focus not only when the View/Usercontrol loads but also if you a changing Views by way of Visibility. If you Hide and then Show a ContentControl that is mapped to your ViewModels then the Loaded event won't fire and you'll be forced to Mouse input, or tabbing (Not so good if you want to navigate your app with a remote control). VisibilityChanged will always fire however. This is what I ended up with for my listbox.

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);
            }));
        }
    }
like image 113
Oli Avatar answered Oct 19 '22 10:10

Oli