Infragistics XamDataGrid选中项切换及焦点异常问题
XamDataGrid网格联动左箭头失效问题解决
我有三个绑定不同数据源的Infragistics XamDataGrid,要实现网格联动功能:选中第一个网格时按下右键头,第一个网格取消选中,第二个网格获得焦点并选中首项,这个功能运行正常;但按下左箭头时功能失效,焦点反而向右移动且没有任何项被选中。左右箭头的目标网格判定逻辑完全一致,却只有左箭头操作出现问题。
问题根源
排查后发现,问题出在未将PreviewKeyDown事件标记为已处理。XamDataGrid自身对左右箭头有默认的键盘导航逻辑,虽然我们在PreviewKeyDown里执行了自定义联动,但未阻止事件继续传递,导致默认逻辑覆盖了自定义操作(左箭头的默认行为可能和右箭头有差异,才出现单边失效的情况)。
原视图代码
<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>
原后台代码
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)); } }
修复方案
只需要在Handle_PreviewKeyDown方法中,处理完自定义逻辑后,将事件标记为已处理,阻止XamDataGrid执行默认的键盘导航:
修改后的Handle_PreviewKeyDown代码:
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); // 标记事件已处理,阻止默认逻辑执行 e.Handled = true; } break; } }
这样修改后,左右箭头都能正确触发自定义的网格联动逻辑,不会再出现左箭头失效的问题。
内容的提问来源于stack exchange,提问作者user8114848
相关产品推荐
相关产品推荐

