c# - Winforms DataGridView在VirtualMode什么时候调用AutoResizeColumn?

标签 c# winforms datagridview autoresize virtualmode

我已在表单上实现了 DataGridView 并成功实现了 VirtualMode。这会从本地缓存检索单元格数据,并且在填充网格/分页等时,所有内容似乎都能正常工作。我处理 DataGridView.CellValueNeeded 事件来填充单元格。

在 DataGridView 上,我将 AutoSizeColumnsMode 属性设置为 DataGridViewAutoSizeColumnsMode.DisplayedCells。我注意到,在使用 VirtualMode 时,填充单元格后,DataGridView 似乎不尊重 AutoSizeColumnsMode。我已经检查过this article但没有找到解决方案。

我最终想做的是不依赖 AutoSizeColumnsMode 属性,而是在某处调用 .AutoResizeColumn() 方法调整大小,因此我最初自动调整列大小,但随后允许用户调整大小。

我尝试了以下方法,但效果有限或没有成功:

  1. DataGridView.AutoSizeColumnsMode设置为.None。然后在我的 .CellValueNeeded 处理程序

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        // ... Get cell value from cache
       dataGridView.AutoResizeColumn(e.ColumnIndex, DataGridViewAutoSizeColumnMode.DisplayedCells);
     }
    

    这会抛出一个 StackOverFlowException 大概是因为它 反复引发.CellValueNeeded

  2. 尝试了完全相同的操作,除了 .CellFormatting 事件处理程序。得到相同的 StackOverFlowException

  3. 尝试使用和不使用DataGridView.SuspendLayout/ResumeLayout:

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        // ... Get cell value from cache
       dataGridView.CellValueNeeded -= dataGridView_CellValueNeeded;
       dataGridView.AutoResizeColumn(e.ColumnIndex, DataGridViewAutoSizeColumnMode.DisplayedCells);
       dataGridView.CellValueNeeded += dataGridView_CellValueNeeded;
    }
    

    这会给出所有空白单元格,因此没有用。

  4. 这个实际上有点作用,但我不明白的原因:

    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        // ... Get cell value from cache
        dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
    }
    

    它正确地调整了列的大小,但必须对所需的每个单元格值重复调用它似乎很奇怪。另外,我不能立即将其设置为 .None,否则它会再次StackOverFlowException。因此,我不能允许用户调整列的大小。

  5. 如文章中所述,从我的 .CellValueNeeded 处理程序调用 .UpdateCellValue() 也会引发 StackOverFlowException

那么是否有可能在某个地方调用 .AutoResizeColumn() ,而在它溢出之前不会引发 .CellValueNeeded ?由于 #4 似乎能够执行自动调整大小功能,似乎我也可以从某个地方手动调用它。

最佳答案

我认为这可能是解决方案,尽管我仍然有兴趣听听其他人的意见。

我继续查看 DataGridView 引发的一些其他事件,并找到了 .RowPostPaint 事件。我创建了以下处理程序:

private void dataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
    if (dataGridView.AllowUserToResizeColumns) //So not to run unnecessarily
    {
        return;
    }
    var lastIndex = dataGridView.Rows.GetLastRow(DataGridViewElementStates.Displayed);
    if (e.RowIndex == lastIndex) //Only do on the last displayed row
    {
        dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
        dataGridView.AllowUserToResizeColumns = true;  // User has control from here on
    }
}

这会在初始数据加载时完成列的自动调整大小,然后允许用户从那里重新调整大小。它只执行一次,因此比所需的每个单元格值要好得多。我必须在初始数据加载之前设置 dataGridView.AllowUserToResizeColumns = false

这似乎符合要求。用户将在初始加载时看到非常适合的列,并可以从那里进行调整,并且我的大多数数据从行到行的长度相当,因此在大多数情况下不应截断或浪费空间。

关于c# - Winforms DataGridView在VirtualMode什么时候调用AutoResizeColumn?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9553022/

相关文章:

c# - DataGridView 列中的计算

c# - 将 DataGridView 单元格值转换为 DateTime

c# - 数据网格和设计器的奇怪 VS2010 行为

c# - Sharepoint 开发教程

c# - Azure函数读取appsetting.json

c# - Linq Groupby 多个同名列(匿名类型不能有多个同名属性)

c# - 带有列表框的 foreach 的奇怪问题

c# - 如何获取用户视频目录?

c# - .NET:您能否手动指定要包含在自动生成的 WSDL 中的类型?

C# - 如何在用户设置中保存文本框和复选框