我已经在我的表单上实现了一个DataGridView,并成功地实现了VirtualMode。这从本地缓存中检索单元数据,在填充网格/分页等时,所有数据似乎都正常工作。我处理DataGridView.CellValueNeeded事件来填充单元格。
在DataGridView上,AutoSizeColumnsMode属性设置为DataGridViewAutoSizeColumnsMode.DisplayedCells。我注意到在使用VirtualMode时,DataGridView在填充单元格后似乎不尊重AutoSizeColumnsMode。我检查了这篇文章,但没有找到解决方案。
我最终想要做的是不依赖AutoSizeColumnsMode属性,而是在某个地方调用.AutoResizeColumn()方法来调整大小,所以我最初自动调整列的大小,然后允许用户调整大小。
我尝试了以下几种方法,结果有限或没有成功:
DataGridView.AutoSizeColumnsMode设置为.None。然后在我的.CellValueNeeded处理程序中
私有dataGridView_CellValueNeeded(对象发送方,DataGridViewCellValueEventArgs e) { // .从缓存DataGridViewAutoSizeColumnMode.DisplayedCells);(e.ColumnIndex,e.ColumnIndex)中获取单元格值
这会抛出一个StackOverFlowException,大概是因为它多次引发.CellValueNeeded。.CellFormatting事件处理程序中,尝试了完全相同的事情。得到了同样的StackOverFlowException。DataGridView.SuspendLayout/ResumeLayout:
私有dataGridView_CellValueNeeded(对象发送方,DataGridViewCellValueEventArgs e) { // .从缓存DataGridViewAutoSizeColumnMode.DisplayedCells);-= dataGridView_CellValueNeeded;dataGridView.AutoResizeColumn(e.ColumnIndex,dataGridView.CellValueNeeded += dataGridView_CellValueNeeded;})获取单元格值。
这给了所有的空白单元格,所以没有用。StackOverFlowException。因此,我不能允许用户调整列的大小。.CellValueNeeded处理程序调用.CellValueNeeded也会抛出StackOverFlowException。那么,是否有可能在.AutoResizeColumn()溢出之前不会引发.CellValueNeeded的地方调用它呢?由于#4似乎具有执行自动大小函数的能力,所以我似乎也可以从某个地方手动调用它。
发布于 2012-03-05 02:32:43
我认为这可能是解决问题的办法,但我仍有兴趣听取其他人的意见。
我继续查看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。
这似乎符合要求。用户将在初始加载时看到很好的适合列,并且可以从那里调整,而且我的大部分数据都是行到行的可比长度,因此在大多数情况下不应该截断或浪费空间。
发布于 2017-03-26 05:56:15
由于您对其他人必须说的内容感兴趣,所以我已经为如何使用虚拟数据网格自动调整列大小提供了一种稍微不同的方法。
在显示事件之后放置初始的AutoResizeColumns调用,以便初始化和显示窗体和子组件。此外,通过连接用于调整大小的DataGridView Scroll事件(而不是RowPostPaint ),这应该会稍微提高一些效率,因为该事件的触发频率较低,而且我认为它与您引用的MSDN引用一起进行得很好:
using System.Collections.Generic;
using System.Windows.Forms;
namespace DataGridViewTest
{
public partial class DataGridViewForm : Form
{
private List<string> dataSource;
public DataGridViewForm()
{
InitializeComponent();
// Enable VirtualMode for dataGridView1
dataGridView1.VirtualMode = true;
// Wire CellValueNeeded event handler
dataGridView1.CellValueNeeded += DataGridView1_CellValueNeeded;
// Wire Scroll event handler
dataGridView1.Scroll += DataGridView1_Scroll;
// Wire form Shown event handler
this.Shown += DataGridViewForm_Shown;
}
private void DataGridViewForm_Shown(object sender, System.EventArgs e)
{
// Populate dataGridView1 here to avoid perception of a long form startup time
populateDataGridView();
// Resize columns after the form is initialized and displayed on screen,
// otherwise calling this method won't actually have an effect on column sizes
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
}
private void DataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// Set the triggering cell's value to the corresponding value from dataSource
e.Value = dataSource[e.RowIndex];
}
private void DataGridView1_Scroll(object sender, ScrollEventArgs e)
{
// Resize columns again, but only if a vertical scroll just happened
if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
{
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
}
}
private void populateDataGridView()
{
fetchIntoDataSource();
associateDataSourceToDataGridView();
}
private void fetchIntoDataSource()
{
dataSource = new List<string>();
// Insert a test string into dataSource many times
for (int i = 0; i < 1000; i++)
{
dataSource.Add("test string");
}
}
private void associateDataSourceToDataGridView()
{
// Synchronize dataGridView1.RowCount to dataSource.Count
// This is necessary for the CellValueNeeded event to fire
dataGridView1.RowCount = dataSource.Count;
}
}
}https://stackoverflow.com/questions/9553022
复制相似问题