C# dataGridView如何在过滤后保持行号不变

C# dataGridView如何在过滤后保持行号不变,c#,.net,winforms,datagridview,C#,.net,Winforms,Datagridview,我有一个datagridview,比如说有8行,我过滤第3、4和5行中包含的值。这意味着在过滤之后,我希望在行标题中看到第3、4、5行。如果我将rowheader值设置为常量,这可能会以某种方式实现 我当前的过滤方法是: BindingSource bs = (BindingSource)Dgv.DataSource; bs.Filter = string.Format(...); Dgv.DataSource = bs; private void dataGridView1_RowPostP

我有一个datagridview,比如说有8行,我过滤第3、4和5行中包含的值。这意味着在过滤之后,我希望在行标题中看到第3、4、5行。如果我将rowheader值设置为常量,这可能会以某种方式实现

我当前的过滤方法是:

BindingSource bs = (BindingSource)Dgv.DataSource;
bs.Filter = string.Format(...);
Dgv.DataSource = bs;
private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
    using (SolidBrush b = new 
    SolidBrush(dataGridView1.RowHeadersDefaultCellStyle.ForeColor))
    {
        e.Graphics.DrawString((e.RowIndex + 1).ToString(), e.InheritedRowStyle.Font, b,
        e.RowBounds.Location.X + 10,
        e.RowBounds.Location.Y + 4);
    }
}
我当前的行编号方法是:

BindingSource bs = (BindingSource)Dgv.DataSource;
bs.Filter = string.Format(...);
Dgv.DataSource = bs;
private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
    using (SolidBrush b = new 
    SolidBrush(dataGridView1.RowHeadersDefaultCellStyle.ForeColor))
    {
        e.Graphics.DrawString((e.RowIndex + 1).ToString(), e.InheritedRowStyle.Font, b,
        e.RowBounds.Location.X + 10,
        e.RowBounds.Location.Y + 4);
    }
}
这会绘制行标题,但每当我过滤它们时,它们都会从一开始就重新编号(1、2、3…)

如果我以这种方式设置行号:

for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
   dgv1.Rows[i].HeaderCell.Value = String.Format("{0}", i + 1);
}
for(int i=0;i

然后在过滤之后,我完全丢失了行标题中的值。因此,我考虑在第一次加载表时给行标题一个常量值?

在筛选时,数字会重新开始,因为
e.RowIndex
将始终运行
DataGridView.Rows
的计数,该计数在筛选时会发生变化

假设您的
BindingSource.DataSource
是一个
DataTable
,您可以通过从非过滤源获取项目的索引来实现您的目标:

private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
    var rowItem = (DataRowView)this.dataGridView1.Rows[e.RowIndex].DataBoundItem;
    int index = ((this.dataGridView1.DataSource as BindingSource).DataSource as DataTable).Rows.IndexOf(rowItem.Row);

    using (SolidBrush b = new SolidBrush(dataGridView1.RowHeadersDefaultCellStyle.ForeColor))
    {
        e.Graphics.DrawString((index + 1).ToString(), e.InheritedRowStyle.Font, b,
        e.RowBounds.Location.X + 10,
        e.RowBounds.Location.Y + 4);
    }
}
如果基础源是的其他实现,则类似地,您需要强制转换行项并在源集合中查找其索引:

var rowItem = (MyObject)this.dataGridView1.Rows[e.RowIndex].DataBoundItem;
int index = ((this.dataGridView1.DataSource as BindingSource).IndexOf(rowItem);

其想法是:您的物品将根据其在主收藏中的顺序进行编号。当应用过滤器时,集合视图会发生更改,但集合本身仍然包含所有对象,因此顺序和编号保持不变。

代码运行良好,我只需处理一个nullreference异常。这是因为当datagridview被填充时,它会自动在最后添加一个空行。在这种情况下,DataBoundItem为null。很高兴你发现了这一点-我禁用了
AllowUserToAddress
,所以我错过了它。