Как установить фокус при перезагрузке страницы WPF?

У меня есть браузерное приложение WPF с несколькими страницами. Когда я переключаюсь между страницами, я хотел бы установить фокус клавиатуры.

Когда страница загружается в первый раз, это работает, вызывая Control.Focus() в конструкторе.

Но когда я переключаюсь между страницами, это больше не работает - фокус находится только на первом поле и игнорирует мои попытки изменить его на что-либо другое :(

Страницы имеют атрибут KeepAlive=true — было бы нормально, если бы он также сохранял фокус, но просто установка фокуса на первое поле раздражает.

Я пытался установить фокус в загруженном событии, но это тоже не сработало. Кажется, что фокус по умолчанию устанавливается после перезагрузки страницы.

Есть ли способ установить фокус на входе на страницу во второй раз? Когда, как и где следует устанавливать фокус при переключении между страницами WPF в браузерном приложении?


person Sam    schedule 07.10.2008    source источник


Ответы (4)


Попробуйте добавить FocusManager.FocusedElement="{Binding ElementName=[...]}"`` к первому элементу на вашей странице и установите [...] на имя элемента, который должен получить фокус.

person Sven Hecht    schedule 20.02.2009

После «Кошмара начального фокуса WPF» и на основе некоторых ответов в стеке следующее оказалось для меня лучшим решением.

Сначала добавьте в App.xaml OnStartup() следующее:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

Затем добавьте событие WindowLoaded также в App.xaml:

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

Проблема с многопоточностью должна использоваться, поскольку первоначальный фокус WPF в основном не работает из-за некоторых условий гонки фреймворка.

Я нашел следующее решение лучшим, поскольку оно используется глобально для всего приложения.

Надеюсь, поможет...

Оран

person OrPaz    schedule 24.01.2011
comment
MoveFocus(new TraversalRequest(FocusNavigationDirection.First)) — оригинальный метод для перемещения фокуса на первый доступный для фокуса дочерний элемент элемента управления. Любить это! - person Josh G; 09.06.2011

Вы пытались установить фокус в обработчике событий Loaded, а не в конструкторе? Страницы не реконструируются, когда вы возвращаетесь к ним, но они перезагружаются, если я правильно помню.

person Matt Hamilton    schedule 07.10.2008
comment
Да, пробовал ставить фокус в событии Loaded - тоже не работает. - person Sam; 07.10.2008

Поскольку я не нашел решения этой проблемы, я использовал простой обходной путь:

Я запускаю дополнительный поток, который меняет фокус после загрузки страницы.

К счастью, это делается очень легко с помощью BeginInvoke:

myControl.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, 
(System.Threading.SendOrPostCallback)delegate(object state) 
{ 
  myControl.Focus(); 
});

Это сработало намного лучше, чем я ожидал, поэтому, вероятно, этот обходной путь будет использоваться еще долгое время.

person Sam    schedule 21.10.2008