Фокусировка с помощью FocusManager, ContentControl и DataTemplate

Я пытаюсь заставить (клавиатурный) фокус работать правильно с приложением следующей структуры:

ItemsControl
  DataTemplate for Item
    ContentControl
      DataTemplate for Content (multiple, depending on type)
        Some container
          Different controls (mainly textbox or OK button should have focus)

В корне каждого шаблона содержимого ("Некоторый контейнер") я устанавливаю FocusManager.FocusedElement к одному элементу управления в шаблоне. Из всех элементов в ItemsControl фактически виден только один из ContentControl ("текущий"). Итак, в основном, я делаю первое, что видно, кнопка ОК в нем имеет фокус, пользователь может нажать Enter для подтверждения. Затем этот скрыт, следующий показан, и его основной элемент управления (например, текстовое поле) имеет фокус, пользователь может нажать клавишу ввода для подтверждения (небольшая обработка события, чтобы ввести в текстовом поле подтверждение элемента) и так далее.

Когда все сделано, пользователь может нажать кнопку на панели инструментов, чтобы начать все сначала, снова делая первый ContentControl видимым. Но на этот раз у него нет фокуса. Я не знаю, у кого есть фокус, я бы хотел, чтобы он работал как в начале. Я попытался установить фокус на только что показанный ContentControl (который работает, видимый через пунктирную линию), но он не установит фокус на своих детей. Поскольку я не знаю, какой из шаблонов данных выбран (ну, не без написания специального кода), я не могу просто установить фокус вручную или с помощью привязки к ребенку. Может быть, я упускаю простую вещь на данный момент?

С другой стороны, когда пользователь вручную нажимает на активную кнопку ContentControl или текстовое поле, он может затем подтвердить ввод, но тогда, кажется, что у ItemsControl есть фокус, а не следующий элемент. Я просто не могу разобраться с этим вопросом. Есть ли простое решение? Нужно ли писать код для обхода дерева из ContentControl, чтобы получить правильную таблицу данных? И затем, я могу просто как-то сфокусировать табличку с данными или элемент управления, установленный как FocusedElement, или мне нужно написать код для каждой таблицы данных отдельно?

1 ответ

Вы должны реализовать действие, которое может быть запущено из ViewModel для фокусировки элемента при необходимости. Попробуйте этот код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interactivity;
using System.Windows;

namespace Behaviors
{
    /// <summary>
    /// Action to focus target element, if invoked when target is not yet specified, will focus once the target is set
    /// </summary>
    public class FocusAction : TargetedTriggerAction<DependencyObject>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
        }
        protected override void OnDetaching()
        {
            base.OnDetaching();
        }
        protected override void Invoke(object parameter)
        {
            if (Target is UIElement)
            {
                if(!((UIElement)Target).IsKeyboardFocusWithin)
                    ((UIElement)Target).Focus();
            }
            else
                invokeOnConnect = true;
        }
        private bool invokeOnConnect = false;
        protected override void OnTargetChanged(DependencyObject oldTarget, DependencyObject newTarget)
        {
            base.OnTargetChanged(oldTarget, newTarget);
            if (invokeOnConnect)
            {
                invokeOnConnect = false;
                Invoke(null);
            }
        }
    }
}

А потом в WPF:

<DockPanel>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <nuib:FocusAction TargetName="title"/>
            </i:EventTrigger>
        <TextBlock x:Name="title"/>
</DockPanel>

пространства имен:

xmlns:nuib="clr-namespace:Behaviors;assembly=Nui" // for Action class
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" // .net library for interactivity
Другие вопросы по тегам