JB06 February 2016

WPF - Setting tab order on large number of controls

So I have a large amount of controls (textboxes) as you can see below, but there are around 30 rows of this. These are loaded using arrays, and each column represents an array. So when I hit tab in a textbox, instead of tabbing horizontally, it tabs vertically instead.

Is there a way to set the tab order so it will tab horizontally, aside from changing the way the controls are loaded?

Another quirk is that when leaving one textbox, instead of focusing the next, it just kind of highlights the textbox, and I have to tab a second time to get inside the next textbox.

enter image description here

EDIT:
Main view (lots of code has been omitted, I'm pretty sure nothing has been left out that needs to be here)

<ListBox ItemsSource="{Binding Items}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">   
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel IsItemsHost="True" />
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
</ListBox>

ItemsView

<UserControl>
  <UserControl.Resources>
    <DataTemplate DataType="{x:Type vm:Item}">
      <views:ItemView/>
    </DataTemplate>
  </UserControl.Resources>

  <StackPanel>
    <ContentControl Content="{Binding item <!-- about 30 different items here, omitted for readability -->}" />
  </StackPanel>
</UserControl>

ItemView

<UserControl ... IsTabStop="False">
  <TextBox Text="{Binding Value}" />
</UserControl>

The ItemView is nested in the ItemsView, which is nested in the MainView. Since the textboxes are generated based on the array values, I can't easily set the TabIndex property unless there is a way I don't know about (

Answers


devuxer February 2016

The TabIndex property provides a way to control the tab order independently of the order controls are loaded.

Usage example:

<Grid>
    <TextBox TabIndex="2" /><!-- will receive focus second -->
    <TextBox TabIndex="1" /><!-- will receive focus first-->
</Grid>

I would guess the unwanted focusing you are seeing is due to a parent UserControl that your TextBoxes are placed in.

If this is the case, you could prevent that by setting IsTabStop="false" on that parent control.

For example:

<UserControl .... IsTabStop="False">
    <Grid>
        <!-- other graphics -->
        <TextBox TabIndex="1" />
    </Grid>
</UserControl>

Using a view model to populate the data

public class CellViewModel
{
    public double Value { get; set; }
    public int TabIndex { get; set; }
}

public IEnumerable<IEnumerable<CellViewModel>> GetMatrix(
    List<List<double>> matrixValues)
{
    var columnCount = matrixValues.Count;
    return matrixValues
        .Select((x, i) => GetColumn(x, columnCount, i));
}

public IEnumerable<CellViewModel> GetColumn(
    List<double> columnValues,
    int columnCount,
    int columnIndex)
{
    return columnValues
        .Select((x, i) =>
            new CellViewModel { Value = x, TabIndex = columnIndex + columnCount * i });
}

Your ItemsSource for your ListBox (which you've now changed to ItemsControl) should be a new Matrix property, which you populate using GetMatrix().

In your ItemView, you would want something like this:

<UserControl ... IsTab 

Post Status

Asked in February 2016
Viewed 1,192 times
Voted 14
Answered 1 times

Search




Leave an answer