调整ListView列以适应WinForms

我有面子调整listview列的问题。 如果您将listview 锚定/停靠到正常winform而不是listview锚点或对接工作正常。 我的意思是listview将resize并适合winforms,因为winforms最大化但是你设计的列没有使用listviewresize。

我的问题是: 有没有办法用listview调整listview列以适应winform大小?

Listview设计代码:

private void Form1_Load(object sender, EventArgs e) { listView1.View = View.Details; listView1.LabelEdit = true; listView1.BackColor = Color.GreenYellow; listView1.Columns.Add("Date", 100, HorizontalAlignment.Left); listView1.Columns.Add("TransID", 50, HorizontalAlignment.Left); listView1.Columns.Add("voucher", 100, HorizontalAlignment.Right); listView1.Columns.Add("particulars", 300, HorizontalAlignment.Left); listView1.Columns.Add("deposit", 100, HorizontalAlignment.Right); listView1.Columns.Add("withdrawal", 100, HorizontalAlignment.Right); string connstr = "server=.;initial catalog=DataBase;uid=UID;pwd=PWD"; SqlConnection con = new SqlConnection(connstr); con.Open(); listView1.Items.Clear(); listView1.Refresh(); string sql = "select date=convert(varchar,date,103),transID,max(particulars)as particulars,sum(deposit)as deposit,sum(withdrawal) as withdrawal,voucher from debank group by date,transID,voucher"; SqlCommand cmd = new SqlCommand(sql, con); SqlDataAdapter dap = new SqlDataAdapter(cmd); DataSet ds = new DataSet(); dap.Fill(ds); DataTable dt = ds.Tables[0]; for (int i = 0; i < dt.Rows.Count; i++) { DataRow dr = dt.Rows[i]; ListViewItem lvi = new ListViewItem(dr["date"].ToString()); lvi.SubItems.Add(dr["transID"].ToString()); lvi.SubItems.Add(dr["voucher"].ToString()); lvi.SubItems.Add(dr["particulars"].ToString()); lvi.SubItems.Add(dr["deposit"].ToString()); lvi.SubItems.Add(dr["withdrawal"].ToString()); listView1.Items.Add(lvi); listView1.FullRowSelect = true; } SizeLastColumn(listView1); } 

  1. 编程之一。 你必须在代码中维护它。
  2. 您可以在列表视图中调整最后一列的大小,以便自动resize。 净样本:

在ListView控件中,将View属性设置为Details,可以创建多列输出。 有时您会希望ListView的最后一列自行resize以占用所有剩余空间。 您可以通过将列宽设置为魔术值-2来完成此操作。

在以下示例中,ListView控件的名称为lvSample:

 [c#] private void Form1_Load(object sender, System.EventArgs e) { SizeLastColumn(lvSample); } private void listView1_Resize(object sender, System.EventArgs e) { SizeLastColumn((ListView) sender); } private void SizeLastColumn(ListView lv) { lv.Columns[lv.Columns.Count - 1].Width = -2; } 

编辑:

Programaticaly你可以用自己实现的算法做到这一点。 问题是列表视图不知道您要resize的列,以及不希望resize的列。 因此,您将在resize方法(或在resizeEmd方法中)指定所有列的大小更改。 因此,您计算列表视图的所有宽度,然后按比例划分所有列之间的值。 您的列宽为50到50.因此,整个列表视图宽度为15 *х(默认状态下x = 50。我根据列数和宽度计算出15个值)常规单位。 调整窗体大小时,可以计算新的x = ListView.Width/15 ,然后将每个列宽设置为所需的值,这样

 private void SizeLastColumn(ListView lv) { int x = lv.Width/15 == 0 ? 1 : lv.Width/15; lv.Columns[0].Width = x*2; lv.Columns[1].Width = x; lv.Columns[2].Width = x*2; lv.Columns[3].Width = x*6; lv.Columns[4].Width = x*2; lv.Columns[5].Width = x*2; } 

这是我的解决方案;

而不是resize事件我更喜欢resizeEnd的forms,以便代码在resize完成时只运行一次。

 private void Form1_ResizeEnd(object sender, EventArgs e) { this.ResizeColumnHeaders(); } 

ResizeColumnHeaders函数设置除最后一列之外的所有列以适合列内容。 最后一列将使用LexRema暗示的魔法值。

 private void ResizeColumnHeaders() { for (int i = 0; i < this.listView.Columns.Count - 1;i++ ) this.listView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent); this.listView.Columns[this.listView.Columns.Count - 1].Width = -2; } 

加载初始数据后,不要忘记调用ResizeColumnHeaders();

 private void Form1_Load(object sender, EventArgs e) { this.LoadEntries(); this.ResizeColumnHeaders(); } 

还有一件事是在列resize时防止闪烁,您需要对列表视图进行双重缓冲。

 public Form1() { InitializeComponent(); this.listView.DoubleBuffer(); } 

DoubleBuffer()实际上是一个易于使用的扩展。

 public static class ControlExtensions { public static void DoubleBuffer(this Control control) { // http://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form/77233#77233 // Taxes: Remote Desktop Connection and painting: http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx if (System.Windows.Forms.SystemInformation.TerminalServerSession) return; System.Reflection.PropertyInfo dbProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); dbProp.SetValue(control, true, null); } } 

您可以按此处所述按内容调整列的大小,或者您必须侦听ListView的Resize事件并在运行时设置列的大小。

一个简单的解决方案,它采用listview和你想要自动resize的列的索引,以便整个listview的客户区域的大小被用于最后一个像素,不多也不少,即使没有丑陋的水平滚动条出现,即使resize使控件更小。

您希望从Resize事件处理程序调用此方法,并且在添加元素之后 ,如果在添加更多行之后出现垂直滚动条,则控件具有垂直空间。

我不同意对ResizeEnd事件作出反应的想法,正如其他post中提到的那样,因为如果Windows设置为在移动和resize时绘制窗口,这在屏幕上看起来不太好。 计算很快,因此不会产生任何连续resize的问题。

 static private void ResizeAutoSizeColumn(ListView listView, int autoSizeColumnIndex) { // Do some rudimentary (parameter) validation. if (listView == null) throw new ArgumentNullException("listView"); if (listView.View != View.Details || listView.Columns.Count <= 0 || autoSizeColumnIndex < 0) return; if (autoSizeColumnIndex >= listView.Columns.Count) throw new IndexOutOfRangeException("Parameter autoSizeColumnIndex is outside the range of column indices in the ListView."); // Sum up the width of all columns except the auto-resizing one. int otherColumnsWidth = 0; foreach (ColumnHeader header in listView.Columns) if (header.Index != autoSizeColumnIndex) otherColumnsWidth += header.Width; // Calculate the (possibly) new width of the auto-resizable column. int autoSizeColumnWidth = listView.ClientRectangle.Width - otherColumnsWidth; // Finally set the new width of the auto-resizing column, if it has changed. if (listView.Columns[autoSizeColumnIndex].Width != autoSizeColumnWidth) listView.Columns[autoSizeColumnIndex].Width = autoSizeColumnWidth; } 

用这个

 Private Sub ListView1_Resize(sender As Object, e As EventArgs) Handles ListView1.Resize Dim k = ListView1.Width - 10 Dim i = k / 3 ListView1.Columns(0).Width = k - i ListView1.Columns(1).Width = i / 2 ListView1.Columns(2).Width = i / 2 End Sub 

三列一个较大,两个较小,大小相同