Introduction
Most of the time, it is important to persist the width of columns in a list view. And this can be done easily. But sometimes you may need to persist, the order, whether a column is a required column, and whether the column should be displayed or not.
The Question
The order and the width are already provided, but whether a column is required or should be displayed is the reason of this article, and my question: "How do I persist these values?".
The Answer
The ListView
in itself does not know anything about this information. So, I decided to implement a ListView
Settings dialog. Columns information is stored to the registry in the order that they should be displayed.
Steps that require attention in the ListView
Settings dialog are:
- Add columns to the dialog.
private void AddDonorCols()
{
reg.ReadDonorSettings();
foreach( MyColumns col in reg.DonorCols)
{
ListViewItem it = listView1.Items.Add(col.name);
it.Checked = col.show;
}
listView1.Focus();
listView1.Items[0].Selected = true;
}
Read columns information from the registry and initialize list with information.
- Moving items up or down.
private void SwapElements(int idx)
{
listView1.BeginUpdate();
ListViewItem it1 = listView1.Items[idx];
ListViewItem it2 = listView1.Items[idx -1];
listView1.Items.RemoveAt(idx);
listView1.Items.RemoveAt(idx - 1);
listView1.Items.Insert(idx-1,it1);
listView1.Items.Insert(idx,it2);
SwapCols(ref reg.m_DonorCols[idx], ref reg.m_DonorCols[idx - 1]);
OnSelectedIndexChanged(null, null);
listView1.Focus();
listView1.EndUpdate();
}
This function is used by the Move up and Move Down buttons. When moved down, the index (idx
) of the element being moved is the index of the next element in the list. When moved up, the index (idx
) of the element being moved is passed to the function.
- Check box is clicked.
private void OnItemChecked(object sender,
System.Windows.Forms.ItemCheckEventArgs e)
{
int idx = e.Index;
if ( reg.m_DonorCols[idx].required == true)
{
e.NewValue = CheckState.Checked;
}
}
When an item is required, you cannot change its checked state. So, you set the NewValue
to checked.
Back to the main ListView
I started by changing the ListView
property HeaderStyle
to NonClickable
, so I will not have to worry about dragging columns. The only worry I will have will be resizing columns, which has been taken care by the article: Persist ListView settings with serialization by dfontanesi.
Steps that need notice in the main ListView
:
- Initialize the
ListView
width:
private void InitDonors()
{
MyReg reg = new MyReg();
reg.ReadDonorSettings();
listView1.BeginUpdate();
listView1.Columns.Clear();
foreach( MyColumns col in reg.m_DonorCols)
{
if ( col.show)
listView1.Columns.Add(col.name,
col.width, HorizontalAlignment.Left);
}
listView1.EndUpdate();
}
- Save
ListView
width:
private void SaveListViewWidths()
{
MyReg reg = new MyReg();
reg.ReadDonorSettings();
foreach( ColumnHeader column in listView1.Columns )
{
LV_COLUMN pcol = new LV_COLUMN();
pcol.mask = LVCF_ORDER;
bool ret = SendMessage(listView1.Handle,
LVM_GETCOLUMN, column.Index, ref pcol);
reg.m_DonorCols[column.Index].width = column.Width;
}
reg.WriteDonorSettings();
}
Well peace, I am out.