While talking with one of our customers, he wanted an additional feature in
one of our programs to let him drop a number of files onto our application and
then modify certain properties of the resulting documents in a list.
Showing these documents in a
ListView can be done easily, but
editing of single properties requires a little work (since built-in
ListView only allows plain editing of a
text). Because I didn't find anything pre-built, I decided to write my own
in-place editing for
ListViews, so here it is...
How it is done
In fact, in-place editing in a
ListView isn't too much magic,
but there are a few places where the plain .NET framework classes aren't
sufficient, so I had to use a little Interop.
First, you have to have a control to perform the actual editing of the
SubItem. Which control you use is (almost) completely up to you.
fine, for example. Since this control is used only when a
has been clicked, it should be invisible in the beginning.
Then you have to find out which
SubItem has been clicked. This
part is quite straightforward, I've added a method
ListViewEx to make things a little easier.
A little twist comes from column reordering. Standard
allows you to rearrange its columns while in report view
AllowColumnReorder property). Unfortunately, there is no built-in
way to find out the current order of your columns, so this is where Interop came
private static extern IntPtr SendMessage(IntPtr hWnd,
int msg, int len, ref int  order);
private const int LVM_FIRST = 0x1000;
private const int LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59);
Using these declarations, you can use the
LVM_GETCOLUMNORDERARRAY message to get the
current column order.
The next step is to move the editor control in place and to make it visible.
Once the actual editing is being performed, the user must be able to accept or
reject any changes he makes, so there are a few events that have to be caught
Usually, a click outside the editor control accepts any changes made, as does
the Return key. Pressing ESC while in in-place editing mode converts back to the
Because the editor control actually is not part of the
I also had to look for any action that might change the size or location of the
editor control. This was done overriding
protected override void WndProc(ref Message msg)
NMHDR h = (NMHDR)Marshal.PtrToStructure(msg.LParam, typeof(NMHDR));
if (h.code == HDN_BEGINDRAG ||
h.code == HDN_ITEMCHANGINGA ||
h.code == HDN_ITEMCHANGINGW)
Here, scrolling and resizing of the
ListView are monitored as
well as changes to the
ListView's column headers. If one of these
messages is received, the input focus is transferred back to the
ListView, thus ending in-place editing.
How to use ListViewEx for in-place editing
There are two ways to perform in-place editing with
First, you can use the new
SubItemClicked event together with
GetSubItemBounds() to position your editor control by yourself, or
you can use
StartEditing(), which performs all required
calculations and control positioning by itself.
So, usually you would start by adding a
ListViewEx and at least
one control used as a cell editor to your
Form. Don't forget to
make your cell editor control invisible! Then wire up an event handler for
SubItemClicked and actually start editing:
private void listViewEx1_SubItemClicked(object sender,
listViewEx1.StartEditing(comboBox1, e.Item, e.SubItem);
I've included a small sample application to show you how to use
ListViewEx with several different cell editors. Feel free to use
the control or the source to your heart's desire and have fun!
Your comments gave me some hints on missing features, so meanwhile I've added
an additional property
DoubleClickActivation so that you can decide
if the ListViewEx should enter editing mode when you click on a subitem or if a
double click is required.
Another point was adding two new events (
SubItemEndEditing) to give the caller the possibility to control
what's displayed in the editing control and what gets put back into the
Now you're able to add a password field as a
cell editor and transfer the plain password to and from the edit control without
having it shown in the listview. Take a look at the sample project to see how
- Update to account for editor control and ListViewEx not sharing the same
parent (thanks Eric-Paul).
Fixed code has been uploaded.
- Reviewed the whole project.
- Fixed a few bugs.
- Added new features (DoubleClickActivation, new events, higher level of
control over the editing process,...