You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:07:28