This article is currently in the process of being translated into Russian (~99% done).
Tab Order
Если вы достаточно много работали с компьютером, чтобы учиться программированию, вы, возможно, знаете, что клавиша Tab на клавиатуре используется для навигации по окнам/диалогам. Это позволяет использовать только клавиатуру, когда вы заполняете формы или что-то подобное, вместо того, чтобы мышью выбирать нужные поля/контролы.
WPF поддерживает это поведение прямо из коробки, и даже лучше: он автоматически устанавливает порядок, используемый при переходе от одного поля к другому, поэтому зачастую вам вообще не нужно беспокоиться об этом. Однако иногда дизайн вашего окна/диалога приводит к такому порядку табуляции, с которым вы по разным причинам не можете согласиться. Кроме того, вы можете решить, что определенные элементы управления не должны быть частью порядка табуляции. Позвольте мне проиллюстрировать это на примере:
Этот диалог состоит из Grid'а, разделенного по центру, со StackPanel на каждой стороне, содержащей метки и текстовые поля. Поведение по умолчанию для последовательности порядка табуляции состоит в том, чтобы начать с первого контрола Window, а затем перейти по каждому из дочерних контролов, найденных в нем, перед переходом к следующему контролу. Поскольку диалог состоит из вертикально ориентированных StackPanels, это будет означать, что мы начнем с поля First name, а затем перейдем к полю Street name и затем к полю City, прежде чем перейти к StackPanel номер два, содержащее поля для Last name и Zip code. По выходе из второго StackPanel две кнопки будут, наконец, достигнуты.
Однако для этого диалога это не то поведение, которое я хочу. Вместо этого я хочу перейти от First name к Last name (перемещаясь по горизонтали, а не по вертикали), и, кроме того, я не хочу вводить City при переходе по форме, поскольку оно будет автоматически заполнено на основе Zip code в этом воображаемом диалоговом окне и, следовательно, сделано только для чтения. Чтобы сделать все это, я буду использовать два свойства: TabIndex иIsTabStop. TabIndex используется для определения порядка, а свойство IsTabStop заставит WPF пропускать элемент управления при проходе по контролам. Вот разметка, используемая для создания диалога:
<Window x:Class="WpfTutorialSamples.Control_concepts.TabOrderSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTutorialSamples.Control_concepts"
mc:Ignorable="d"
Title="TabOrderSample" Height="250" Width="400">
<Grid Margin="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel>
<Label>First name:</Label>
<TextBox TabIndex="0" />
<Label>Street name:</Label>
<TextBox TabIndex="2" />
<Label>City:</Label>
<TextBox TabIndex="5" IsReadOnly="True" IsTabStop="False" Background="Gainsboro" />
</StackPanel>
<StackPanel Grid.Column="2">
<Label>Last name:</Label>
<TextBox TabIndex="1" />
<Label>Zip Code:</Label>
<TextBox TabIndex="4" />
</StackPanel>
<Button Grid.Row="1" HorizontalAlignment="Right" Width="80">Add</Button>
<Button Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" Width="80">Cancel</Button>
</Grid>
</Window>
Смотрите, как я просто присваиваю каждому соответствующему элементу управления номер в свойстве TabIndex, а затем использую IsTabStop для TextBox, используемого для City - вот так просто контролировать порядок вкладок в диалоге!
Сводка
Контролирование порядка табуляции в диалогах очень важно, но, к счастью для нас, WPF проделывает хорошую работу по автоматическому определению порядка переключения для нас. Однако в некоторых случаях имеет смысл взять это под свой контроль, используя свойства TabIndex и IsTabStop, так, как это проиллюстрировано в примерах сверху.