datagridview虚拟模式,更新RowCount会导致CellValueNeeded为所有行触发

时间:2011-12-06 17:46:54

标签: c# .net winforms datagridview

我正在尝试实现datagridview的虚拟模式,但是当我将RowCount设置为某个数字(以显示滚动条)时,网格想要同时拥有所有行,而不仅仅是显示的。

DataGridView grid = new ...;

grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = dataprovider.GetFullCount();

如何告诉网格只请求显示的行?

5 个答案:

答案 0 :(得分:4)

这只是一个猜测,但您是将AutoSizeRowsMo​​de或AutoSizeColumnsMode值设置为AllCells还是设置为该列的任何列?尝试将调整大小模式设置为无或仅显示DisplayedCells并查看是否仍有问题。

答案 1 :(得分:2)

不确定这是否与我遇到的问题相同,但是当我在VirtualMode DataGridView上经常大幅更改RowCount时,我确实得到了非常差的性能。

我注意到滚动条正在“慢慢地”变化;即它看起来像是单独删除我的虚拟行(!)。

无论如何,在每次调用grid.Rows.Clear()之前执行grid.RowCount = n会大幅改善效果。

答案 2 :(得分:0)

不幸的是,这似乎是标准行为。我可以通过

解决它
void OnCellValueNeeded(...)
{
    if(!_active) return;
}

grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
_active = false;
grid.RowCount = dataprovider.GetFullCount();
_active = true;

或实现IBindingList,ITypedList在后台线程中使用复杂的延迟抓取

更新:现在问题似乎已解决。我无法再使用以下内容重现它​​:

static class Program
{
    private static Form form;
    private static int i;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        var grid = new DataGridView
        {
            Dock = DockStyle.Fill,
            VirtualMode = true,
            AllowUserToAddRows = false,
            Columns =
            {
                new DataGridViewTextBoxColumn { HeaderText = "foo" },
                new DataGridViewTextBoxColumn { HeaderText = "bar" },
            },
        };
        grid.CellValueNeeded += OnCellValueNeeded;
        form = new Form
        {
            Controls = { grid }
        };

        //grid.RowCount = 0;
        grid.RowCount = 10000;

        Application.Run(form);
    }

    private static void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        i++;
        form.Text = i.ToString();
        e.Value = "fooValue";
    }
}

答案 3 :(得分:0)

我遇到了同样的问题,我尝试了像你一样设置活动标志的解决方案,我也尝试了在设置新的之前将RowCount设置为0(或grid.Rows.Clear())的解决方案行数。

这两件事都提高了性能,但是它们都没有足够快,因为我根据搜索框的输入实时动态过滤网格。

我找到了另外两个解决方案:

1)使用分页,这样您就不必将RowCount设置得如此之高。我认为这是一个很好的解决方案,如果你已经使用分页(在这种情况下你不会在这里),但如果你没有计划实现它,那就太麻烦了。

2)调用将RowCount设置为自己的线程。这是我即将尝试的那个。老实说,如果你在线程仍在完成时尝试编辑单元格,那么这个单元是多么安全,但我想我很快就会发现。

编辑:

好的,所以我试着穿上它,希望能做到这一点,因为我在其他地方读到这真的帮助了另一个人。它似乎是一个很好的解决方案 IF 你只是偶尔改变一下这个值,但是如果你连续多次这样做(我就是这样)它仍然会挂起。我想这是因为你必须使用Invoke(),第二次它还在等待第一次完成。不能说我完全理解这笔交易是什么,但是我决定暂时使用空白行,因为当我把它们留在那里时它的SOOO更快更简单。

答案 4 :(得分:0)

在设置完整计数之前,应将RowCount设置为零。

DataGridView grid = new ...;
grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = 0;
grid.RowCount = dataprovider.GetFullCount();