Клавиша навигации WPF - PullRequest
11 голосов
/ 17 декабря 2011

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

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

enter image description here

Ответы [ 4 ]

36 голосов
/ 27 декабря 2011

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 пользовательского элемента управления вместо того, чтобы не забывать устанавливать эту привязку на всех элементах управления внутри пользовательского элемента управления. Я уверен, что есть и более эффективные способы сделать это, однако проблема не возникала достаточно часто, чтобы я мог сесть и найти время, чтобы изучить, как правильно использовать области табуляции, чтобы избежать этого обходного пути.

9 голосов
/ 25 декабря 2011

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

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

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

5 голосов
/ 31 декабря 2011

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

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

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

// 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

С уважением,

0 голосов
/ 28 июня 2012

Попробуйте KeyboardNavigation.TabNavigation = "Once"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...