C# ListView根据列内容和标题自动调整列大小
我们使用这两种方法根据列内容和标题resp来调整列长度 AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)C# ListView根据列内容和标题自动调整列大小,c#,winforms,visual-studio-2010,C#,Winforms,Visual Studio 2010,我们使用这两种方法根据列内容和标题resp来调整列长度 AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize) 但如何根据两者进行调整?i、 e.调整标题和列内容的最长长度 lvw.Columns[0]。宽度=-2 有关详细信息,请参见MSDN中的备注: 还要注意,MSDN说“要自动调整列标题的宽度,请将widt
但如何根据两者进行调整?i、 e.调整标题和列内容的最长长度
lvw.Columns[0]。宽度=-2
有关详细信息,请参见MSDN中的备注:
还要注意,MSDN说“要自动调整列标题的宽度,请将width属性设置为-2”,但实际上它适用于列标题和列内容
下面是一个代码来证明:
lvw.Columns.Add(new String('x', 25)); // short header
lvw.Items.Add(new String('x', 100)); // long content
lvw.Columns[0].Width = -2;
// in result column width will be set to fit content
这就是我用来调整内容和标题的列宽的方法:
public static void autoResizeColumns(ListView lv)
{
lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
ListView.ColumnHeaderCollection cc = lv.Columns;
for (int i = 0; i < cc.Count; i++)
{
int colWidth = TextRenderer.MeasureText(cc[i].Text, lv.Font).Width + 10;
if (colWidth > cc[i].Width)
{
cc[i].Width = colWidth;
}
}
}
该方法没有经过很好的测试,但至少它在我使用它的环境中工作。正如所回答的,调用两个调整大小选项可以完成这项工作:
myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
myListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
在我的例子中,我通过以下步骤(对于两列数据):
'Create two header objects as ColumnHeader Class
Dim header1, header2 As ColumnHeader
'Construcción de los objetos header
header1 = New ColumnHeader
header1.Text = "ID"
header1.TextAlign = HorizontalAlignment.Right
header1.Width = 10
header2 = New ColumnHeader
header2.Text = "Combinaciones a Procesar"
header2.TextAlign = HorizontalAlignment.Left
header2.Width = 10
'Add two columns using your news headers objects
ListView.Columns.Add(header1)
ListView.Columns.Add(header2)
'Fill three rows of data, for each column
ListView.Items.Add(New ListViewItem({"A1", "B1"}))
ListView.Items.Add(New ListViewItem({"A2", "B2"}))
ListView.Items.Add(New ListViewItem({"A3", "B3"}))
'Change the size of each column
Dim headsz1, headsz2 As Integer
SelectionInTable.ListView.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.HeaderSize)
SelectionInTable.ListView.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.HeaderSize)
headsz1 = header1.Width
headsz2 = header2.Width
SelectionInTable.ListView.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent)
SelectionInTable.ListView.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent)
headsz1 = Math.Max(headsz1, header1.Width)
headsz2 = Math.Max(headsz2, header2.Width)
header1.Width = headsz1
header2.Width = headsz2
这里有一个C#解决方案,可以用于任何ListView。它假定您的列计数和标题对于任何给定的列表视图都不会更改。如果要每次重新计算标题宽度(如果标题更改或列数更改),请删除listViewHeaderWidths字典
private Dictionary listViewHeaderWidths=new Dictionary();
私有void ResizeListViewColumns(ListView lv)
{
int[]headerWidths=listViewHeaderWidths.ContainsKey(lv.Name)?listViewHeaderWidths[lv.Name]:null;
lv.BeginUpdate();
if(headerWidths==null)
{
lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
headerWidths=newint[lv.Columns.Count];
for(int i=0;i
Anton Kedrov的答案是最好的,但在我的例子中,我有一个超过50列的listview,我经常更新它的数据。在这种情况下,我注意到listview的this.AutoResizeColumns执行更快的工作,所以我也在编写这个解决方案
第一种方法是设置为-2
public void AutoUpdateColumnWidth(ListView lv)
{
for (int i = 0; i <= lv.Columns.Count - 1; i++) {
lv.Columns(i).Width = -2;
}
}
public void AutoUpdateColumnWidth(ListView lv)
{
对于(int i=0;i,确实可以使用MeasureText,然后计算剩余空间的多少,并以某种方式在所有列之间分配。但这是一种快速而肮脏的方法,我已经快速编写了:
/// <summary>
/// Enables autoresizing for specific listview.
/// You can specify how much to scale in columnScaleNumbers array - length of that array
/// should match column count which you have.
/// </summary>
/// <param name="listView">control for which to enable auto-resize</param>
/// <param name="columnScaleNumbers">Percentage or numbers how much each column will be scaled.</param>
private void EnableAutoresize(ListView listView, params int[] columnScaleNumbers)
{
listView.View = View.Details;
for( int i = 0; i < columnScaleNumbers.Length; i++ )
{
if( i >= listView.Columns.Count )
break;
listView.Columns[i].Tag = columnScaleNumbers[i];
}
listView.SizeChanged += lvw_SizeChanged;
DoResize(listView);
}
void lvw_SizeChanged(object sender, EventArgs e)
{
ListView listView = sender as ListView;
DoResize(listView);
}
bool Resizing = false;
void DoResize( ListView listView )
{
// Don't allow overlapping of SizeChanged calls
if (!Resizing)
{
// Set the resizing flag
Resizing = true;
if (listView != null)
{
float totalColumnWidth = 0;
// Get the sum of all column tags
for (int i = 0; i < listView.Columns.Count; i++)
totalColumnWidth += Convert.ToInt32(listView.Columns[i].Tag);
// Calculate the percentage of space each column should
// occupy in reference to the other columns and then set the
// width of the column to that percentage of the visible space.
for (int i = 0; i < listView.Columns.Count; i++)
{
float colPercentage = (Convert.ToInt32(listView.Columns[i].Tag) / totalColumnWidth);
listView.Columns[i].Width = (int)(colPercentage * listView.ClientRectangle.Width);
}
}
}
// Clear the resizing flag
Resizing = false;
}
这将按以下方式分配列大小:
6*100%/(6+3+1)=第一列的60%,
下次30%,剩余10%
这在某种程度上是穷人的快速实现。:-这很简单(尽管我花了一段时间才弄明白)
我们知道宽度必须至少与列标题一样大,这样我们才能看到所有标题文本。除此之外,宽度可以扩展得更大以容纳内容。因此,我们执行以下操作:
将列自动调整为标题
遍历列并将每列的“最小宽度”属性设置为当前列宽(这保证了列不会太小而看不到标题)
从现在起,按内容自动调整列的大小
不必单独跟踪宽度并按照其他海报的建议重置它们。设置列的最小宽度可以解决问题,直到标题文本更改为止。在这种情况下,您可以将最小宽度设置为0,仅自动调整修改的列的大小,然后将最小宽度再次设置为当前宽度
编辑:很抱歉,我忘了我没有使用标准listview,而是使用第三方产品BetterListView(提供免费版本)。标准listview列似乎不支持最小宽度。我强烈推荐BetterListView作为一个很好的替代方案(更好的功能集和性能).我认为这是不对的,甚至MSDN也说:要自动调整列标题的宽度,请将width属性设置为-2。因此,它只根据标题而不是标题和内容调整大小。如果MSDN link误导了您,很抱歉。它旨在表明使用此神奇数字是合法的。“-2”同时考虑标题和内容。我更改了我的答案以澄清这一点。我认为您和MSDN都不正确。从我的测试中,您声称通常正确的内容仅适用于视图中的最后一列。对于最后一列,-2
(或LVSCW\u AUTOSIZE\u USEHEADER
)值,根据doc,width设置为填充列表视图控件的剩余宽度。但实际上它将其设置为剩余宽度和列或标题内容长度的最大值。但这仅适用于最后一列。在您的示例中,什么是有效的,因为您只有一列。如果您只更新一次数据,但一次又一次地更新数据我只是创建一个ListViewitem,在每个子项中填充标题文本,然后调用对列内容重新调整大小,然后简单地删除我添加的项这将减少对每个列的强制重新调整大小我添加了代码作为新的答案,如果它有助于某个人的话谢谢
public void AutoUpdateColumnWidth(ListView lv)
{
for (int i = 0; i <= lv.Columns.Count - 1; i++) {
lv.Columns(i).Width = -2;
}
}
public void AutoUpdateColumnWidth(ListView lv)
{
ListViewItem nLstItem = new ListViewItem(lv.Columns(0).Text);
for (int i = 1; i <= lv.Columns.Count - 1; i++) {
nLstItem.SubItems.Add(lv.Columns(i).Text);
}
v.Items.Add(nLstItem);
lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
lv.Items.RemoveAt(nLstItem.Index);
}
/// <summary>
/// Enables autoresizing for specific listview.
/// You can specify how much to scale in columnScaleNumbers array - length of that array
/// should match column count which you have.
/// </summary>
/// <param name="listView">control for which to enable auto-resize</param>
/// <param name="columnScaleNumbers">Percentage or numbers how much each column will be scaled.</param>
private void EnableAutoresize(ListView listView, params int[] columnScaleNumbers)
{
listView.View = View.Details;
for( int i = 0; i < columnScaleNumbers.Length; i++ )
{
if( i >= listView.Columns.Count )
break;
listView.Columns[i].Tag = columnScaleNumbers[i];
}
listView.SizeChanged += lvw_SizeChanged;
DoResize(listView);
}
void lvw_SizeChanged(object sender, EventArgs e)
{
ListView listView = sender as ListView;
DoResize(listView);
}
bool Resizing = false;
void DoResize( ListView listView )
{
// Don't allow overlapping of SizeChanged calls
if (!Resizing)
{
// Set the resizing flag
Resizing = true;
if (listView != null)
{
float totalColumnWidth = 0;
// Get the sum of all column tags
for (int i = 0; i < listView.Columns.Count; i++)
totalColumnWidth += Convert.ToInt32(listView.Columns[i].Tag);
// Calculate the percentage of space each column should
// occupy in reference to the other columns and then set the
// width of the column to that percentage of the visible space.
for (int i = 0; i < listView.Columns.Count; i++)
{
float colPercentage = (Convert.ToInt32(listView.Columns[i].Tag) / totalColumnWidth);
listView.Columns[i].Width = (int)(colPercentage * listView.ClientRectangle.Width);
}
}
}
// Clear the resizing flag
Resizing = false;
}
EnableAutoresize(listView1, 6, 3, 1);