
Introduction
One of my favorite things to do in .NET is to work with XML. Many times, users are asking if they can modify ListView columns at run-time. I've seen solutions, saving client-side preferences into databases. It is not wrong but it is not practical, considering that this data is not really related to the business-model design.
Background
Working often with systems providing a lot of information causes a difficulty level for developers to find a way to design flexible and user-friendly applications. ListView controls with a large amount of columns are one of these things, for example.
Then, how to modify a ListView control at run-time?
Using the code
The source code under the download session was made in Microsoft Visual Studio .NET 2003 - Enterprise Architect. I experienced issues compiling it in previous .NET studio versions.
Now, we need to add the following items into our solution:
- A form hosting our
ListView control.
- Another form allowing us to modify the
ListView at run time.
- A
DataSet.
In the following example, we create a DataSet and name it to ListviewColumns.xsd. In the Toolbox option, drag and drop an Element, and finally in this Element, add a row Columns of type string (see figures 1 and 2).

Figure 1

Figure 2
On the main form (ListviewFrm), drag and drop a ListView control and set the following properties to it:
View: Details
FullRowSelect: True
Name: mMainListviewLvw
I also added a button (mColumnsBtn). In the mColumnsBtn_Click event, I added the following code to make an instance of my second form:
private void mColumnsBtn_Click(object sender, System.EventArgs e)
{
ListviewPropertiesFrm listviewProperties = new ListviewPropertiesFrm();
listviewProperties.Show();
}
In ListviewFrm, under the ListviewApp_Load event, I call a method ReadXMLColumns:
private void ListviewApp_Load(object sender, System.EventArgs e)
{
ReadXMLColumns();
}
ReadXMLColumns creates a ListviewColumns typed DataSet, and retrieves the data from ListviewColumns.xml file through the ReadXml method.
private void ReadXMLColumns()
{
ListviewColumns sr;
DataTable dt;
DataColumn dc;
sr = new ListviewColumns();
dt = new DataTable("ListviewColumn");
dc = new DataColumn();
sr.Tables.Add(dt);
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = "CheckBoxName";
dt.Columns.Add(dc);
string xmlDocPath =
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
xmlDocPath = xmlDocPath + "/ListViewApp";
if (!Directory.Exists(xmlDocPath))
{
Directory.CreateDirectory(xmlDocPath);
}
else
{
if (File.Exists(xmlDocPath + "/ListviewColumns.xml"))
{
sr.ReadXml(xmlDocPath + "/ListviewColumns.xml");
BuildColumnHeaders(sr);
}
}
}
BuildColumnHeaders goes through the DataSet, and finally adds the columns in our ListView by calling the BuildColumn method.
private void BuildColumnHeaders(DataSet sr)
{
int i = 0;
foreach(DataRow dr in sr.Tables[0].Rows)
{
string checkBoxName = dr["CheckBoxName"].ToString();
switch (checkBoxName)
{
case "First Column":
i = BuildColumn("First Column", i);
break;
case "Second Column":
i = BuildColumn("Second Column", i);
break;
case "Third Column":
i = BuildColumn("Third Column", i);
break;
}
}
}private int BuildColumn(string columnHeaderName, int i)
{
ColumnHeader col = new ColumnHeader();
col.Text = columnHeaderName;
col.Width = 100;
mMainListviewLvw.Columns.Add(col);
i ++;
return i;
}
ListviewFrm will now be able to read the XML file and display the columns. However, we need to add functionality in order to modify our XML file, therefore it is time to see what is going on in the ListviewPropertiesFrm.
On our second form (ListviewPropertiesFrm), add the following controls (see figure 3):
- Three
CheckBoxes (First Column, Second Column and Third Column)
- OK and Cancel
Buttons

Figure 3
In the mOkBtn_Click event, I call the ColumnsToXML method:
private void mOkBtn_Click(object sender, System.EventArgs e)
{
Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
ListviewColumnsToXML();
Cursor.Current = System.Windows.Forms.Cursors.Default;
Close();
}
In ListviewColumnsToXML method, we create a typed DataSet, then loop through the form controls, and add the CheckBoxes into our DataSet. Finally, we export them into XML by using the WriteXml method.
private void ListviewColumnsToXML()
{
ListviewColumns sr;
DataRow dr;
DataTable dt;
DataColumn dc;
sr = new ListviewColumns();
dt = new DataTable("ListviewColumn");
dc = new DataColumn();
sr.Tables.Add(dt);
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = "CheckBoxName";
dt.Columns.Add(dc);
foreach(Control mControl in this.Controls)
{
if (mControl.GetType().ToString() == "System.Windows.Forms.CheckBox")
{
CheckBox C;
C = (CheckBox) mControl;
if (C.Checked)
{
dr = dt.NewRow();
dr["CheckBoxName"].ToString();
dr["CheckBoxName"] = mControl.Text;
dt.Rows.Add(dr);
}
}
}
string xmlDocPath = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
xmlDocPath = xmlDocPath + "/ListViewApp";
if (!Directory.Exists(xmlDocPath))
{
Directory.CreateDirectory(xmlDocPath);
sr.WriteXml(xmlDocPath + "/ListviewColumns.xml");
}
else
{
sr.WriteXml(xmlDocPath + "/ListviewColumns.xml");
}
}
We are almost done, but we need to add a few things on our ListviewPropertiesFrm_Load event. In order to have our check boxes be checked, or not checked each time we open this form, we need to retrieve the XML data. I use the two methods for that. The first method would do the same things like the ReadXMLColumns did in ListviewFrm, and the second method would set the CheckBoxes' Checked property to true.
Points of Interest
The best way of designing a special ListView for your needs, is to follow an object oriented design. In other words, inherit .NET ListView into a new class, write additional functionality into it, and then create a DLL where you can add it to your future solutions. This ListView could have additional functionality, such as column sorting, pop-up menu, export to Excel, etc.