I have 3 XamDataGrids each with a different source, I want the different grids to act together so if the first grid is selected and the right arrow is pressed, the first grid should be deselected and the second grid should be focused and the first item in the second grid should be selected. This is working correctly, however, pressing the left arrow key does not seem to work. Focus is actually going to the right and no item is being selected. The logic used to determine the next grid is the same for both left and right clicks but for some reason only the left arrow key is causing issues.
View:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <dataPresenter:XamDataGrid Grid.Column="0" x:Name="Grid1" DataSource="{Binding Grid1Source}" PreviewKeyDown="Handle_PreviewKeyDown"/> <dataPresenter:XamDataGrid Grid.Column="1" x:Name="Grid2" DataSource="{Binding Grid2Source}" PreviewKeyDown="Handle_PreviewKeyDown"/> <dataPresenter:XamDataGrid Grid.Column="2" x:Name="Grid3" DataSource="{Binding Grid3Source}" PreviewKeyDown="Handle_PreviewKeyDown"/> </Grid>
Code Behind:
public TestView() { InitializeComponent(); viewmodel = // Get ViewModel DataContext = viewmodel; viewmodel.Initialize(); } private void Handle_PreviewKeyDown(object sender, KeyEventArgs e) { var currentGrid = sender as XamDataGrid; switch (e.Key) { case Key.Left: case Key.Right: var grid = GetNextGrid(currentGrid, e); if (grid != null) { ChangeGrid(currentGrid, grid); } break; } } private void ChangeGrid(XamDataGrid previousGrid, XamDataGrid nextGrid) { previousGrid.SelectedItems.Records.Clear(); previousGrid.ActiveRecord = null; nextGrid.SelectedItems.Records.Clear(); nextGrid.ActiveRecord = null; nextGrid.SelectedItems.Records.Add(nextGrid.Records[0]); nextGrid.SelectedDataItem = nextGrid.Records[0]; nextGrid.Focus(); } private XamDataGrid GetNextGrid(XamDataGrid currentGrid, KeyEventArgs e) { switch (currentGrid.Name) { case "Grid1": if (e.Key == Key.Left) { return Grid3.Records.Count > 0 ? Grid3 : Grid2.Records.Count > 0 ? Grid2 : null; } else if (e.Key == Key.Right) { return Grid2.Records.Count > 0 ? Grid2 : Grid3.Records.Count > 0 ? Grid3 : null; } break; case "Grid2": if (e.Key == Key.Left) { return Grid1.Records.Count > 0 ? Grid1 : Grid3.Records.Count > 0 ? Grid3 : null; } else if (e.Key == Key.Right) { return Grid3.Records.Count > 0 ? Grid3 : Grid1.Records.Count > 0 ? Grid1 : null; } break; case "Grid3": if (e.Key == Key.Left) { return Grid2.Records.Count > 0 ? Grid2 : Grid1.Records.Count > 0 ? Grid1 : null; } else if (e.Key == Key.Right) { return Grid1.Records.Count > 0 ? Grid1 : Grid2.Records.Count > 0 ? Grid2 : null; } break; } return null; }
ViewModel:
public class TestViewModel : INotifyPropertyChanged { #region variables public event PropertyChangedEventHandler PropertyChanged; private ObservableCollection<string> grid1Source = new ObservableCollection<string>(); private ObservableCollection<string> grid2Source = new ObservableCollection<string>(); private ObservableCollection<string> grid3Source = new ObservableCollection<string>(); public ObservableCollection<string> Grid1Source { get => grid1Source; set { grid1Source = value; RaisePropertyChanged(nameof(Grid1Source)); } } public ObservableCollection<string> Grid2Source { get => grid2Source; set { grid2Source = value; RaisePropertyChanged(nameof(Grid2Source)); } } public ObservableCollection<string> Grid3Source { get => grid3Source; set { grid3Source = value; RaisePropertyChanged(nameof(Grid3Source)); } } #endregion #region INotify public void RaisePropertyChanged(string propertyname) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyname)); } } # endregion public TestViewModel() { Grid1Source = new ObservableCollection<string> { "Grid1 Test1", "Grid1 Test2", "Grid1 Test3", "Grid1 Test4", "Grid1 Test5" }; Grid2Source = new ObservableCollection<string> { "Grid2 Test1", "Grid2 Test2", "Grid2 Test3", "Grid2 Test4" }; Grid3Source = new ObservableCollection<string> { "Grid3 Test1", "Grid3 Test2", "Grid3 Test3" }; } public void Initialize() { RaisePropertyChanged(nameof(Grid1Source)); RaisePropertyChanged(nameof(Grid2Source)); RaisePropertyChanged(nameof(Grid3Source)); } }
Thanks Andrew for sharing useful information.
Seems like 2 was the solution, thanks Andrew!
Hello Shael,
I have been investigating into the code you have provided, and I believe that there are a couple of issues that may be causing this to not work correctly. I will discuss them below:
1. The following line won't cause an exception, but it is not valid either:
nextGrid.SelectedDataItem = nextGrid.Records[0];
The SelectedDataItem property expects the underlying data item from your data collection – not a Record. This will be filled in by the previous line that adds the nextGrid.Records[0] to the nextGrid.SelectedItems.Records collection though, so you can remove this line.
2. I believe you may be causing a conflict between the built-in XamDataGrid keyboard navigation and yours. To prevent this, I would recommend marking the PreviewKeyDown event handled (e.Handled = true) in the case of your Left and Right key presses.
The above changes should allow your grid to work as you expect.
Please let me know if you have any other questions or concerns on this matter.