简体   繁体   中英

WPF DataGrid DataGridRow override ItemsPanel breaks tab order

I am working on a WPF project that needs a 2D grid that needs to expand and contract within a window. In order to do this I have replaced the ItemsPanels within the DataGrid with UniformGrids. When I do this, the control expands and contracts correctly.

Unfortunately, for some reason this breaks the tab order within the DataGrid. If you press tab, it will drop down a row rather than jump right to the next column. When the tab hits the end of the row, it will go to the top of the next column and continue down it. The left,right,up,down arrow keys all work as expected, the only functionality affected is the tab order. If I remove the DataGridRow Style, the tab order will correct itself, but the rows will not expand with the window.

This problem does not seem to be isolated to the UniformGrid either as a StackPanel also produces the same tab symptoms.

Does anyone know how or what I should look for to fix this tab issue or possibly another way to make the grid expand and contract as required?

Example XAML:

<Window x:Class="SODatagridSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <UniformGrid IsItemsHost="True" Rows="1" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Grid>
        <DataGrid x:Name="datagrid" ItemsSource="{Binding Values}" SelectionMode="Extended"  SelectionUnit="Cell" ColumnWidth="*" HeadersVisibility="None"
                  CanUserAddRows="False" CanUserDeleteRows="False">
            <DataGrid.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="1"></UniformGrid>
                </ItemsPanelTemplate>
            </DataGrid.ItemsPanel>
        </DataGrid>
    </Grid>
</ScrollViewer>

Example Code behind:

using System.ComponentModel;
using System.Data;
using System.Windows;

namespace SODatagridSample
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public DataTable Values
        {
            get { return _Values; }
            set
            {
                _Values = value;
                OnPropertyChanged(nameof(Values));
            }
        }
        private DataTable _Values;

        public MainWindow()
        {
            Values = new DataTable();

            for (int i = 0; i < 15; i++)
                Values.Columns.Add(i.ToString(), typeof(double));

            for (int i = 0; i < 10; i++)
                Values.Rows.Add(Values.NewRow());

            for (int x = 0; x < 10; x++)
                for (int y = 0; y < 15; y++)
                    Values.Rows[x][y] = x * 15 + y;

            DataContext = this;
            InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

The fix was super simple. After reflecting out DataGridCellPanel, I noticed it had the following static constructor:

static DataGridCellsPanel()
        {
            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(DataGridCellsPanel), new FrameworkPropertyMetadata((object)KeyboardNavigationMode.Local));
        }

All that was required was to either extend UniformGrid to add that static constructor or just add an attached property KeyboardNavigation.TabNavigation="Local" to the UniformGrid in the DataGridRow style:

        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <UniformGrid KeyboardNavigation.TabNavigation="Local" IsItemsHost="True" Rows="1"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM