Autosizing Listview Columns

G

Guest

I am writing an application for the Pocket PC and I am using Compact Framework 1.1. I have a Listview that I am populating with data. I need each column to automatically size itself to the longest piece of data in the column. The documentation says the following.

"The ColumnHeader can be set to adjust at run time to the column contents or heading. To adjust the width of the longest item in the column, set the Width property to -1. To autosize to the width of the column heading, set the Width property to -2."

This doesn't work properly. If I set the Column widths AFTER populating the data, the columns totally disappear (if I set it to -1 or -2).

So, I then tried setting the column widths to -1 or -2 upon creation of the Column Headers. In either case (setting to -1 or -2), the same result is produced, which is autosizing the columns to their HEADER size. I need to autosize to the DATA in that column.

I have noticed that if I double tap on the edge of each header, it correctly resizes that column to the width of the data it contains.

How can I get around this? I need to autosize to the data size, not the column header text. Is there a way I can "fake" a double tap on each column when I am done populating the data?

Thanks in advance!
 
P

Patrick Seymour

I recall having this problem when I was missing a service pack for CF 1.0,
but you say you're using 1.1, so that's probably not it.

Anyway, I set my columns to be the width of the column header text or the
widest item's text, whichever is wider. Like so:


foreach (ColumnHeader col in viewControl.Columns)
{
col.Width = -1;
int contentWidth = col.Width;
col.Width = -2;
int headerWidth = col.Width;
col.Width = Math.Max(contentWidth, headerWidth);
}


Brent Lang said:
I am writing an application for the Pocket PC and I am using Compact
Framework 1.1. I have a Listview that I am populating with data. I need
each column to automatically size itself to the longest piece of data in the
column. The documentation says the following.
"The ColumnHeader can be set to adjust at run time to the column contents
or heading. To adjust the width of the longest item in the column, set the
Width property to -1. To autosize to the width of the column heading, set
the Width property to -2."
This doesn't work properly. If I set the Column widths AFTER populating
the data, the columns totally disappear (if I set it to -1 or -2).
So, I then tried setting the column widths to -1 or -2 upon creation of
the Column Headers. In either case (setting to -1 or -2), the same result
is produced, which is autosizing the columns to their HEADER size. I need
to autosize to the DATA in that column.
I have noticed that if I double tap on the edge of each header, it
correctly resizes that column to the width of the data it contains.
How can I get around this? I need to autosize to the data size, not the
column header text. Is there a way I can "fake" a double tap on each column
when I am done populating the data?
 
P

Pete Vickers [eMVP]

Hi,
try this using sendmessage...

Declare Function SendMessage Lib "Coredll" Alias "SendMessageW" (ByVal hWnd
As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As
Integer) As Integer
Declare Function GetFocus Lib "Coredll" () As Integer
Const LVM_SETCOLUMNWIDTH = &H101E
Const LVS_EX_GRADIENT = &H20000000
Const LVM_SETEXTENDEDLISTVIEWSTYLE = &H1000 + 54

Public Shared Sub Autosize_Listview(ByVal lv As Windows.Forms.ListView)
lv.Focus()

Dim col2adjust As Integer
For col2adjust = 0 To lv.Columns.Count - 1
Call SendMessage(GetFocus(), _
LVM_SETCOLUMNWIDTH, _
col2adjust, _
-2)
Next

End Sub

HTH

Pete

--
Pete Vickers
Microsoft Windows Embedded MVP
HP Business Partner
http://www.gui-innovations.com

Brent Lang said:
I am writing an application for the Pocket PC and I am using Compact
Framework 1.1. I have a Listview that I am populating with data. I need
each column to automatically size itself to the longest piece of data in the
column. The documentation says the following.
"The ColumnHeader can be set to adjust at run time to the column contents
or heading. To adjust the width of the longest item in the column, set the
Width property to -1. To autosize to the width of the column heading, set
the Width property to -2."
This doesn't work properly. If I set the Column widths AFTER populating
the data, the columns totally disappear (if I set it to -1 or -2).
So, I then tried setting the column widths to -1 or -2 upon creation of
the Column Headers. In either case (setting to -1 or -2), the same result
is produced, which is autosizing the columns to their HEADER size. I need
to autosize to the DATA in that column.
I have noticed that if I double tap on the edge of each header, it
correctly resizes that column to the width of the data it contains.
How can I get around this? I need to autosize to the data size, not the
column header text. Is there a way I can "fake" a double tap on each column
when I am done populating the data?
 
R

Richard Thombs

This works for me:

foreach (ColumnHeader col in listView.Columns)
{
col.Width=-1;
if (col.Width == 12) col.Width=0; // If the column doesn't contain
anything at all, this will set the size to nothing, so it won't display.
}

R.
 
S

Serg Kuryata [MS]

Could you please post a simple application that reproduces the problem?

Thank you,
Sergiy.

This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| Thread-Topic: Autosizing Listview Columns
| thread-index: AcRd73zg8kxenWh8QXyEq14YOHUuDQ==
| X-WBNR-Posting-Host: 66.155.235.146
| From: "=?Utf-8?B?QnJlbnQgTGFuZw==?=" <Brent
(e-mail address removed)>
| Subject: Autosizing Listview Columns
| Date: Tue, 29 Jun 2004 08:41:04 -0700
| Lines: 13
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="Utf-8"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Content-Class: urn:content-classes:message
| Importance: normal
| Priority: normal
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 127.0.0.1
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGXA01.phx.gbl!TK2MSFTNGXA03.phx.gbl
| Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.framework.compactframework:56204
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
| I am writing an application for the Pocket PC and I am using Compact
Framework 1.1. I have a Listview that I am populating with data. I need
each column to automatically size itself to the longest piece of data in
the column. The documentation says the following.
|
| "The ColumnHeader can be set to adjust at run time to the column contents
or heading. To adjust the width of the longest item in the column, set the
Width property to -1. To autosize to the width of the column heading, set
the Width property to -2."
|
| This doesn't work properly. If I set the Column widths AFTER populating
the data, the columns totally disappear (if I set it to -1 or -2).
|
| So, I then tried setting the column widths to -1 or -2 upon creation of
the Column Headers. In either case (setting to -1 or -2), the same result
is produced, which is autosizing the columns to their HEADER size. I need
to autosize to the DATA in that column.
|
| I have noticed that if I double tap on the edge of each header, it
correctly resizes that column to the width of the data it contains.
|
| How can I get around this? I need to autosize to the data size, not the
column header text. Is there a way I can "fake" a double tap on each
column when I am done populating the data?
|
| Thanks in advance!
|
 
G

Guest

Here is a sample app that wil reproduce the problem. It is a ListView with a button you can press to populate the control with 2 items, some long data and short data. I broke the program down into 4 regions. The first region is active while the others are totally commented out. You can uncomment each section and see the results. The 4th region, which uses PInvoke correctly resizes the columns, the other 3 regions all don't work properly. If I have discovered a bug, please let me know. I hope this helps you track down the problem. Thank you!


using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace ListViewSample
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListView lstData;
private System.Windows.Forms.Button cmdPopulate;
private System.Windows.Forms.MainMenu mainMenu1;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.lstData = new System.Windows.Forms.ListView();
this.cmdPopulate = new System.Windows.Forms.Button();
//
// lstData
//
this.lstData.Location = new System.Drawing.Point(8, 16);
this.lstData.Size = new System.Drawing.Size(224, 176);
this.lstData.View = System.Windows.Forms.View.Details;
//
// cmdPopulate
//
this.cmdPopulate.Location = new System.Drawing.Point(16, 216);
this.cmdPopulate.Size = new System.Drawing.Size(208, 40);
this.cmdPopulate.Text = "Populate Data";
this.cmdPopulate.Click += new System.EventHandler(this.cmdPopulate_Click);
//
// Form1
//
this.Controls.Add(this.cmdPopulate);
this.Controls.Add(this.lstData);
this.MaximizeBox = false;
this.Menu = this.mainMenu1;
this.MinimizeBox = false;
this.Text = "List View Sample";

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>

static void Main()
{
Application.Run(new Form1());
}

private void cmdPopulate_Click(object sender, System.EventArgs e) {
lstData.Columns.Clear();
lstData.Items.Clear();

//create some sample data
string [] SampleData = new string[2];
SampleData[0] = "Small";
SampleData[1] = "Here is some long data. Let's see if the Control resizes itself properly.";

#region ATTEMPT #1
/////////////////////Create some column headers setting the width to -1, so that it
/////adjusts to the width of the longest item in the colum. This doesn't work.
ColumnHeader [] Columns = new ColumnHeader[2];
Columns[0] = new ColumnHeader();
Columns[0].Text = "Data 1";
Columns[0].Width = -1;

Columns[1] = new ColumnHeader();
Columns[1].Text = "Data 2";
Columns[1].Width = -1;

lstData.Columns.Add(Columns[0]);
lstData.Columns.Add(Columns[1]);

ListViewItem lvi = new ListViewItem(SampleData);
lstData.Items.Add(lvi);
#endregion

#region ATTEMPT #2 - SAME RESULTS AS ATTEMPT #1
/////////////////////Create some column headers setting the width to -2, so that it
/////adjusts to the width of the column heading. This doesn't work. this has the same
/////effect as setting to -1.
// ColumnHeader [] Columns = new ColumnHeader[2];
// Columns[0] = new ColumnHeader();
// Columns[0].Text = "Data 1";
// Columns[0].Width = -2;
//
// Columns[1] = new ColumnHeader();
// Columns[1].Text = "Data 2";
// Columns[1].Width = -2;
//
// lstData.Columns.Add(Columns[0]);
// lstData.Columns.Add(Columns[1]);
//
// ListViewItem lvi = new ListViewItem(SampleData);
// lstData.Items.Add(lvi);
#endregion

#region ATTEMPT #3 - COLUMNS DISAPPEAR FROM THE LISTVIEW ALL TOGETHER
/////////////////////Create some column headers setting the width so that each column is half
/////////////////////the width of the control, and then setting the columns to -2 after
////////////////////the data has been populated. Whether I set this to -1 or -2 the effect is
////////////////////the same, the columns just totally disappear from the control.
// ColumnHeader [] Columns = new ColumnHeader[2];
// Columns[0] = new ColumnHeader();
// Columns[0].Text = "Data 1";
// Columns[0].Width = lstData.Width / 2;
//
// Columns[1] = new ColumnHeader();
// Columns[1].Text = "Data 2";
// Columns[1].Width = lstData.Width / 2;
//
// lstData.Columns.Add(Columns[0]);
// lstData.Columns.Add(Columns[1]);
//
// ListViewItem lvi = new ListViewItem(SampleData);
// lstData.Items.Add(lvi);
//
// for (int I = 0; I < lstData.Columns.Count; ++I) {
// //lstData.Columns.Width = -1;
// lstData.Columns.Width = -2;
// }
#endregion

#region ATTEMPT #4 - THIS WORKS USING PINVOKE!
// ColumnHeader [] Columns = new ColumnHeader[2];
// Columns[0] = new ColumnHeader();
// Columns[0].Text = "Data 1";
// Columns[0].Width = lstData.Width / 2;
//
// Columns[1] = new ColumnHeader();
// Columns[1].Text = "Data 2";
// Columns[1].Width = lstData.Width / 2;
//
// lstData.Columns.Add(Columns[0]);
// lstData.Columns.Add(Columns[1]);
//
// ListViewItem lvi = new ListViewItem(SampleData);
// lstData.Items.Add(lvi);
//
// SizeUsingMessage(lstData);
#endregion
}

private void SizeUsingMessage(ListView lst) {
int LVM_SETCOLUMNWIDTH = 0x101E;
lst.Focus();

//sending this message with -1 or -2 DOES have the desired effect!
for (int Col2Adjust = 0; Col2Adjust < lst.Columns.Count; ++Col2Adjust) {
//SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust, -1);
SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust, -2);
}
}

[DllImport("coredll.dll", EntryPoint = "SendMessageW")]
private static extern int SendMessage(int hWnd, int wMsg, int wParam, int lParam);

[DllImport("coredll.dll")]
private static extern int GetFocus();
}
}
 
S

Serg Kuryata [MS]

Fist of all, thank you very much for providing the sample application!

I wonder if you have Service Pack 2 for the .NET Compact Framework
installed. If you don't, please install it. The reason why I'm asking is
that I tried to run your application against SP2 and the scenario #3 worked
just fine without any problems - columns were resized correctly and none of
them disappeared.

Problems #1 and #2 are known problems. The workaround for them is to set
width of the columns after populating listview with items. By the way, if
in the scenario #4, where p/invoke is used, you p/invoke to set the width
after adding columns but before adding items, you'll see the same problem
as in scenarios #1 and #2:

lstData.Columns.Add(Columns[0]);
lstData.Columns.Add(Columns[1]);

SizeUsingMessage(lstData);

ListViewItem lvi = new ListViewItem(SampleData);
lstData.Items.Add(lvi);

I would also encourage you to try to run the same code on desktop - you'll
be surprised!

In order to understand the problem better and see what we could do here I
spoke to a developer who implemented the ListView class. He explained me
that the reason why we see these issues is the design of the native
control. The native listview control was design in such a way that, if you
want to use -1 and -2 for column width then you have to populate the
listview control with items before setting width of the columns. The reason
for that is that native control does not remember that the width was set to
-1 or -2; it just recalculates width of its columns according to the data
that they contain at that moment. So, if width of a column is set to -1
when there is no items, the column will be resized to some minimal size and
the result will be the same as in scenario #1.

I hope I was able to explain the problem. I you have any questions please
let me, I will be glad to help you.

Thank you,
Sergiy.

This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| Thread-Topic: Autosizing Listview Columns
| thread-index: AcRemIQcGEgwciXdQMCaailY+P85mg==
| X-WBNR-Posting-Host: 66.155.235.146
| From: "=?Utf-8?B?QnJlbnQgTGFuZw==?=" <[email protected]>
| References: <[email protected]>
<[email protected]>
| Subject: RE: Autosizing Listview Columns
| Date: Wed, 30 Jun 2004 04:51:01 -0700
| Lines: 197
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="Utf-8"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Content-Class: urn:content-classes:message
| Importance: normal
| Priority: normal
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 127.0.0.1
| Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTFEED02.phx.gbl!TK2MSFTNGXA0
1.phx.gbl!TK2MSFTNGXA03.phx.gbl
| Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.framework.compactframework:56301
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
| Here is a sample app that wil reproduce the problem. It is a ListView
with a button you can press to populate the control with 2 items, some long
data and short data. I broke the program down into 4 regions. The first
region is active while the others are totally commented out. You can
uncomment each section and see the results. The 4th region, which uses
PInvoke correctly resizes the columns, the other 3 regions all don't work
properly. If I have discovered a bug, please let me know. I hope this
helps you track down the problem. Thank you!
|
|
| using System;
| using System.Drawing;
| using System.Collections;
| using System.Windows.Forms;
| using System.Data;
| using System.Runtime.InteropServices;
|
| namespace ListViewSample
| {
| /// <summary>
| /// Summary description for Form1.
| /// </summary>
| public class Form1 : System.Windows.Forms.Form
| {
| private System.Windows.Forms.ListView lstData;
| private System.Windows.Forms.Button cmdPopulate;
| private System.Windows.Forms.MainMenu mainMenu1;
|
| public Form1()
| {
| //
| // Required for Windows Form Designer support
| //
| InitializeComponent();
|
| //
| // TODO: Add any constructor code after InitializeComponent call
| //
| }
| /// <summary>
| /// Clean up any resources being used.
| /// </summary>
| protected override void Dispose( bool disposing )
| {
| base.Dispose( disposing );
| }
| #region Windows Form Designer generated code
| /// <summary>
| /// Required method for Designer support - do not modify
| /// the contents of this method with the code editor.
| /// </summary>
| private void InitializeComponent()
| {
| this.mainMenu1 = new System.Windows.Forms.MainMenu();
| this.lstData = new System.Windows.Forms.ListView();
| this.cmdPopulate = new System.Windows.Forms.Button();
| //
| // lstData
| //
| this.lstData.Location = new System.Drawing.Point(8, 16);
| this.lstData.Size = new System.Drawing.Size(224, 176);
| this.lstData.View = System.Windows.Forms.View.Details;
| //
| // cmdPopulate
| //
| this.cmdPopulate.Location = new System.Drawing.Point(16, 216);
| this.cmdPopulate.Size = new System.Drawing.Size(208, 40);
| this.cmdPopulate.Text = "Populate Data";
| this.cmdPopulate.Click += new
System.EventHandler(this.cmdPopulate_Click);
| //
| // Form1
| //
| this.Controls.Add(this.cmdPopulate);
| this.Controls.Add(this.lstData);
| this.MaximizeBox = false;
| this.Menu = this.mainMenu1;
| this.MinimizeBox = false;
| this.Text = "List View Sample";
|
| }
| #endregion
|
| /// <summary>
| /// The main entry point for the application.
| /// </summary>
|
| static void Main()
| {
| Application.Run(new Form1());
| }
|
| private void cmdPopulate_Click(object sender, System.EventArgs e) {
| lstData.Columns.Clear();
| lstData.Items.Clear();
|
| //create some sample data
| string [] SampleData = new string[2];
| SampleData[0] = "Small";
| SampleData[1] = "Here is some long data. Let's see if the
Control resizes itself properly.";
|
| #region ATTEMPT #1
| /////////////////////Create some column headers setting the
width to -1, so that it
| /////adjusts to the width of the longest item in the colum.
This doesn't work.
| ColumnHeader [] Columns = new ColumnHeader[2];
| Columns[0] = new ColumnHeader();
| Columns[0].Text = "Data 1";
| Columns[0].Width = -1;
|
| Columns[1] = new ColumnHeader();
| Columns[1].Text = "Data 2";
| Columns[1].Width = -1;
|
| lstData.Columns.Add(Columns[0]);
| lstData.Columns.Add(Columns[1]);
|
| ListViewItem lvi = new ListViewItem(SampleData);
| lstData.Items.Add(lvi);
| #endregion
|
| #region ATTEMPT #2 - SAME RESULTS AS ATTEMPT #1
| /////////////////////Create some column headers setting the
width to -2, so that it
| /////adjusts to the width of the column heading. This doesn't
work. this has the same
| /////effect as setting to -1.
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = -2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = -2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| #endregion
|
| #region ATTEMPT #3 - COLUMNS DISAPPEAR FROM THE LISTVIEW ALL
TOGETHER
| /////////////////////Create some column headers setting the
width so that each column is half
| /////////////////////the width of the control, and then setting
the columns to -2 after
| ////////////////////the data has been populated. Whether I set
this to -1 or -2 the effect is
| ////////////////////the same, the columns just totally disappear
from the control.
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = lstData.Width / 2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = lstData.Width / 2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| //
| // for (int I = 0; I < lstData.Columns.Count; ++I) {
| // //lstData.Columns.Width = -1;
| // lstData.Columns.Width = -2;
| // }
| #endregion
|
| #region ATTEMPT #4 - THIS WORKS USING PINVOKE!
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = lstData.Width / 2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = lstData.Width / 2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| //
| // SizeUsingMessage(lstData);
| #endregion
| }
|
| private void SizeUsingMessage(ListView lst) {
| int LVM_SETCOLUMNWIDTH = 0x101E;
| lst.Focus();
|
| //sending this message with -1 or -2 DOES have the desired
effect!
| for (int Col2Adjust = 0; Col2Adjust < lst.Columns.Count;
++Col2Adjust) {
| //SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust,
-1);
| SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust, -2);

| }
| }
|
| [DllImport("coredll.dll", EntryPoint = "SendMessageW")]
| private static extern int SendMessage(int hWnd, int wMsg, int
wParam, int lParam);
|
| [DllImport("coredll.dll")]
| private static extern int GetFocus();
| }
| }
|
|
 
G

Guest

Thanks alot. Since I was able to work around the problem using the P/Invoke, I am just going to leave the code that way. I mean, don't fix what isn't broken right?

Also, it would be more hassle than it is worth to install the SP just for that issue, know what I mean?

Thank you for your detailed explanation of what is going on under the hood though, it was very interesting. Thanks again!

Serg Kuryata said:
Fist of all, thank you very much for providing the sample application!

I wonder if you have Service Pack 2 for the .NET Compact Framework
installed. If you don't, please install it. The reason why I'm asking is
that I tried to run your application against SP2 and the scenario #3 worked
just fine without any problems - columns were resized correctly and none of
them disappeared.

Problems #1 and #2 are known problems. The workaround for them is to set
width of the columns after populating listview with items. By the way, if
in the scenario #4, where p/invoke is used, you p/invoke to set the width
after adding columns but before adding items, you'll see the same problem
as in scenarios #1 and #2:

lstData.Columns.Add(Columns[0]);
lstData.Columns.Add(Columns[1]);

SizeUsingMessage(lstData);

ListViewItem lvi = new ListViewItem(SampleData);
lstData.Items.Add(lvi);

I would also encourage you to try to run the same code on desktop - you'll
be surprised!

In order to understand the problem better and see what we could do here I
spoke to a developer who implemented the ListView class. He explained me
that the reason why we see these issues is the design of the native
control. The native listview control was design in such a way that, if you
want to use -1 and -2 for column width then you have to populate the
listview control with items before setting width of the columns. The reason
for that is that native control does not remember that the width was set to
-1 or -2; it just recalculates width of its columns according to the data
that they contain at that moment. So, if width of a column is set to -1
when there is no items, the column will be resized to some minimal size and
the result will be the same as in scenario #1.

I hope I was able to explain the problem. I you have any questions please
let me, I will be glad to help you.

Thank you,
Sergiy.

This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| Thread-Topic: Autosizing Listview Columns
| thread-index: AcRemIQcGEgwciXdQMCaailY+P85mg==
| X-WBNR-Posting-Host: 66.155.235.146
| From: "=?Utf-8?B?QnJlbnQgTGFuZw==?=" <[email protected]>
| References: <[email protected]>
<[email protected]>
| Subject: RE: Autosizing Listview Columns
| Date: Wed, 30 Jun 2004 04:51:01 -0700
| Lines: 197
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="Utf-8"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Content-Class: urn:content-classes:message
| Importance: normal
| Priority: normal
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 127.0.0.1
| Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTFEED02.phx.gbl!TK2MSFTNGXA0
1.phx.gbl!TK2MSFTNGXA03.phx.gbl
| Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.framework.compactframework:56301
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
| Here is a sample app that wil reproduce the problem. It is a ListView
with a button you can press to populate the control with 2 items, some long
data and short data. I broke the program down into 4 regions. The first
region is active while the others are totally commented out. You can
uncomment each section and see the results. The 4th region, which uses
PInvoke correctly resizes the columns, the other 3 regions all don't work
properly. If I have discovered a bug, please let me know. I hope this
helps you track down the problem. Thank you!
|
|
| using System;
| using System.Drawing;
| using System.Collections;
| using System.Windows.Forms;
| using System.Data;
| using System.Runtime.InteropServices;
|
| namespace ListViewSample
| {
| /// <summary>
| /// Summary description for Form1.
| /// </summary>
| public class Form1 : System.Windows.Forms.Form
| {
| private System.Windows.Forms.ListView lstData;
| private System.Windows.Forms.Button cmdPopulate;
| private System.Windows.Forms.MainMenu mainMenu1;
|
| public Form1()
| {
| //
| // Required for Windows Form Designer support
| //
| InitializeComponent();
|
| //
| // TODO: Add any constructor code after InitializeComponent call
| //
| }
| /// <summary>
| /// Clean up any resources being used.
| /// </summary>
| protected override void Dispose( bool disposing )
| {
| base.Dispose( disposing );
| }
| #region Windows Form Designer generated code
| /// <summary>
| /// Required method for Designer support - do not modify
| /// the contents of this method with the code editor.
| /// </summary>
| private void InitializeComponent()
| {
| this.mainMenu1 = new System.Windows.Forms.MainMenu();
| this.lstData = new System.Windows.Forms.ListView();
| this.cmdPopulate = new System.Windows.Forms.Button();
| //
| // lstData
| //
| this.lstData.Location = new System.Drawing.Point(8, 16);
| this.lstData.Size = new System.Drawing.Size(224, 176);
| this.lstData.View = System.Windows.Forms.View.Details;
| //
| // cmdPopulate
| //
| this.cmdPopulate.Location = new System.Drawing.Point(16, 216);
| this.cmdPopulate.Size = new System.Drawing.Size(208, 40);
| this.cmdPopulate.Text = "Populate Data";
| this.cmdPopulate.Click += new
System.EventHandler(this.cmdPopulate_Click);
| //
| // Form1
| //
| this.Controls.Add(this.cmdPopulate);
| this.Controls.Add(this.lstData);
| this.MaximizeBox = false;
| this.Menu = this.mainMenu1;
| this.MinimizeBox = false;
| this.Text = "List View Sample";
|
| }
| #endregion
|
| /// <summary>
| /// The main entry point for the application.
| /// </summary>
|
| static void Main()
| {
| Application.Run(new Form1());
| }
|
| private void cmdPopulate_Click(object sender, System.EventArgs e) {
| lstData.Columns.Clear();
| lstData.Items.Clear();
|
| //create some sample data
| string [] SampleData = new string[2];
| SampleData[0] = "Small";
| SampleData[1] = "Here is some long data. Let's see if the
Control resizes itself properly.";
|
| #region ATTEMPT #1
| /////////////////////Create some column headers setting the
width to -1, so that it
| /////adjusts to the width of the longest item in the colum.
This doesn't work.
| ColumnHeader [] Columns = new ColumnHeader[2];
| Columns[0] = new ColumnHeader();
| Columns[0].Text = "Data 1";
| Columns[0].Width = -1;
|
| Columns[1] = new ColumnHeader();
| Columns[1].Text = "Data 2";
| Columns[1].Width = -1;
|
| lstData.Columns.Add(Columns[0]);
| lstData.Columns.Add(Columns[1]);
|
| ListViewItem lvi = new ListViewItem(SampleData);
| lstData.Items.Add(lvi);
| #endregion
|
| #region ATTEMPT #2 - SAME RESULTS AS ATTEMPT #1
| /////////////////////Create some column headers setting the
width to -2, so that it
| /////adjusts to the width of the column heading. This doesn't
work. this has the same
| /////effect as setting to -1.
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = -2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = -2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| #endregion
|
| #region ATTEMPT #3 - COLUMNS DISAPPEAR FROM THE LISTVIEW ALL
TOGETHER
| /////////////////////Create some column headers setting the
width so that each column is half
| /////////////////////the width of the control, and then setting
the columns to -2 after
| ////////////////////the data has been populated. Whether I set
this to -1 or -2 the effect is
| ////////////////////the same, the columns just totally disappear
from the control.
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = lstData.Width / 2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = lstData.Width / 2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| //
| // for (int I = 0; I < lstData.Columns.Count; ++I) {
| // //lstData.Columns.Width = -1;
| // lstData.Columns.Width = -2;
| // }
| #endregion
|
| #region ATTEMPT #4 - THIS WORKS USING PINVOKE!
| // ColumnHeader [] Columns = new ColumnHeader[2];
| // Columns[0] = new ColumnHeader();
| // Columns[0].Text = "Data 1";
| // Columns[0].Width = lstData.Width / 2;
| //
| // Columns[1] = new ColumnHeader();
| // Columns[1].Text = "Data 2";
| // Columns[1].Width = lstData.Width / 2;
| //
| // lstData.Columns.Add(Columns[0]);
| // lstData.Columns.Add(Columns[1]);
| //
| // ListViewItem lvi = new ListViewItem(SampleData);
| // lstData.Items.Add(lvi);
| //
| // SizeUsingMessage(lstData);
| #endregion
| }
|
| private void SizeUsingMessage(ListView lst) {
| int LVM_SETCOLUMNWIDTH = 0x101E;
| lst.Focus();
|
| //sending this message with -1 or -2 DOES have the desired
effect!
| for (int Col2Adjust = 0; Col2Adjust < lst.Columns.Count;
++Col2Adjust) {
| //SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust,
-1);
| SendMessage(GetFocus(), LVM_SETCOLUMNWIDTH, Col2Adjust, -2);

| }
| }
|
| [DllImport("coredll.dll", EntryPoint = "SendMessageW")]
| private static extern int SendMessage(int hWnd, int wMsg, int
wParam, int lParam);
|
| [DllImport("coredll.dll")]
| private static extern int GetFocus();
| }
| }
|
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top