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

过滤BindingSource后如何保持DataGridView指定数据行持续为首个展示行

实现方案

核心逻辑:过滤、排序操作会导致DataTable的原始行索引和DataGridView的显示行索引不匹配,因此不要依赖DataTable的原始索引控制滚动位置,通过业务唯一标识(本场景为id列)在当前生效的绑定视图中查询实时索引,再设置首显行即可。

推荐实现(性能最优)

直接利用BindingSource的Find方法,该方法会直接在已经应用过滤、排序的当前视图中查询目标行的索引,返回的索引可直接赋值给DataGridView.FirstDisplayedScrollingRowIndex,无需遍历行,适合高频更新的场景。

代码示例

// 窗体初始化或BindingSource初始化时绑定ListChanged事件,列表变更自动触发定位
bindingSource1.ListChanged += (sender, e) =>
{
    // 仅在列表重置、行删除、行数据变更时执行定位,减少不必要的性能消耗
    if (e.ListChangedType is ListChangedType.Reset 
        or ListChangedType.ItemDeleted 
        or ListChangedType.ItemChanged)
    {
        // 按唯一id查询目标行在当前过滤后视图中的索引,"id"替换为你实际的主键列名
        int targetIndex = bindingSource1.Find("id", 300);
        // 索引有效时设置为首显行
        if (targetIndex >= 0 
            && dataGridView1.FirstDisplayedScrollingRowIndex != targetIndex)
        {
            dataGridView1.FirstDisplayedScrollingRowIndex = targetIndex;
        }
    }
};

兼容实现(适配自定义校验场景)

如果你需要对目标行做额外的自定义校验,可以遍历DataGridView当前的显示行匹配目标id:

// 每次数据刷新/过滤应用后执行
int targetIndex = -1;
int targetId = 300;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
    if (row.Cells["id"].Value != null 
        && Convert.ToInt32(row.Cells["id"].Value) == targetId)
    {
        targetIndex = row.Index;
        break;
    }
}
if (targetIndex >= 0)
{
    dataGridView1.FirstDisplayedScrollingRowIndex = targetIndex;
}

内容的提问来源于stack exchange,提问作者user3584783

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 08:06:03