WPF Tab Key Navigation

У нас есть приложение на основе WPF.NET 4.0 С#. Мы создали наш пользовательский интерфейс из определений XML (а не XAML), но под ним мы используем WPF для представления пользовательского интерфейса. То есть во время выполнения мы создаем интерфейс WPF на основе нашего определения XML.

У нас есть проблема с навигацией на вкладке. Мы устанавливаем TabStop, TabIndex, для текстовых и комбинированных элементов управления.
Но вкладка не работает. Как сделать вкладку навигации для этого макета?

enter image description here

Ответ 1

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

Например, если у вас

<StackPanel>
    <TextBox Name="TextBox1" />
    <MyUserControl />
    <TextBox Name="TextBox3" />
</StackPanel>

И MyUserControl выглядел как

<MyUserControl>
    <TextBox Name="TextBox2"  />
</MyUserControl>

Цикл табуляции по умолчанию будет TextBox1, TextBox2, TextBox3. Это связано с тем, что никаких свойств TabIndex не определены, поэтому все элементы управления выполняются в соответствии с порядком табуляции по умолчанию, который является порядком, в котором они добавлены в пользовательский интерфейс.

Если вы установите TabIndex на своих элементах управления, например ниже,

<StackPanel>
    <TextBox Name="TextBox1" TabIndex="1" />
    <MyUserControl TabIndex="2" />
    <TextBox Name="TextBox3" TabIndex="3" />
</StackPanel>

Ваша вкладка изменится на TextBox1, TextBox3, TextBox2. Это связано с тем, что в TextBox2 не указан указатель TabIndex, поэтому предполагается, что значение по умолчанию включено, и оно имеет вкладку после того, как все остальные элементы управления с указанным TabIndex получают циклический переход.

Как я обычно обойдусь, это связать TabIndex элементов управления внутри UserControl с UserControl.TabIndex.

Например, добавление следующей привязки к UserControl приведет к правильному повторению цикла Tab

<MyUserControl>
    <TextBox Name="TextBox2" TabIndex="{Binding Path=TabIndex, RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}}" />
</MyUserControl>

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

Ответ 2

Вам следует попробовать установить прикрепленное свойство KeyboardNavigation.TabNavigation либо в вашем элементе управления Tree, либо в производном элементе StackPanel, если вы хотите, чтобы ваши нижние кнопки также участвовать в цикле табуляции:

<controls:CustomStackPanel KeyboardNavigation.TabNavigation="Cycle">
 <Tree>
 ...
 </Tree>
</controls:CustomStackPanel>

Вы даже можете комбинировать подход, основанный на использовании кода, который, как я полагаю, в настоящее время пытается использовать для управления ведением вкладок внутри элемента управления Tree, с помощью KeyboardNavigation.TabNavigation, чтобы заботиться о табуляции вне элемента управления деревьями.

Ответ 3

Не каждый ответ, но WPF-табуляция крайне затруднительна. Требуется установить свойства TabNavigation, IsTabStop в Xaml и возиться с фокусом. Я потратил несколько дней, пытаясь правильно использовать табуляцию, используя только Xaml. Я бы предложил начать с вашей модели XML → WPF, которая действительно должна быть Xaml → WPF! Однако я бы подумал, что это невозможно.

Как насчет этого для обходного пути. Можно ли обрабатывать табуляцию в сгенерированном коде? Если ваши пользовательские элементы управления WPF генерируются вашим собственным программным обеспечением из вашего собственного XML, я бы предложил поместить элемент TabOrder в ваш XML и затем использовать его для подключения события TabOut.

Посмотрите на следующий пример кода, чтобы заставить операцию перемещения в коде (аналогично Tabbing)

// Creating a FocusNavigationDirection object to perform the tab operation
// values include Next, Previous, First, Last etc...
FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;

// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);

// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

// Change keyboard focus.
if (elementWithFocus != null)
{
    elementWithFocus.MoveFocus(request);
}

Во-вторых, подключитесь к событию KeyUp (или PreviewKeyUp) ваших "tabbable" элементов управления, и если ключ был вызван табуляцией вышеуказанного кода, чтобы заставить фокус перейти к следующему элементу.

Вышеприведенный пример кода будет в основном заставлять код, который WPF должен делать из коробки. Как и другие плакаты, я предложил бы пройти через созданный код WPF, чтобы узнать, какие значения KeyboardNavigation.IsTabStop и KeyboardNavigation.TabNavigation

С уважением,

Ответ 4

Try KeyboardNavigation.TabNavigation = "После"