|
|
Determining If Icon Was Clicked in ListViewAdding Icons to ListView | | Can I add an Icon to a ListView and tell whether the Icon was clicked when a row is selected in the ListView? You can do all of that and more. This article will show you how to add Icons to the rows in a ListView and how to determine if the Icon was clicked and what row it was, because the Icon will be changed based on it's value before being clicked.
The Icons that I am going to use are simple Plus and Minus Icons because in a later article I will show you how to Expand and Collapse Items in a Listview. So let's get started. The code for this article will be in C#, but it is so straight forward that you should be able to convert it to VB.NET if you so desire.
First, I will create a new C# Windws Application. This will create Form1 and to that form I will add a ListView, named lvIconDemo, to it. I will then go to the ListView Designer and add 3 columns to the ListView. The width of the first column, which will hold the Icon is 25, and the width of the other 2 is 100. I will also set the FullRowSelect property of the ListView to True and the View Property to Details. Next, I will add a Label to the bottom of the form. There, I will show the status of mouse clicking. The designed form will have the following appearence when it is run.
Figure 1 - Running the Application.

Now for the code behind the form. First, the code for the form load event. It calls the method to load the ListView and is shown below.
private void Form1_Load(object sender, EventArgs e)
{
LoadTheListView();
}
|
The code to load the ListView is shown next. It is simple and loads three rows with three columns each; the Icon is in the first column with no text.
/// <summary>
/// Load the demo listview with 3 rows of data and Icons
///
private void LoadTheListView()
{
ListViewItem lvi;
lvi = lvIconDemo.Items.Add("", 0);
lvi.SubItems.Add("Data Row 1");
lvi.SubItems.Add("Column 3 Data 1");
lvi = lvIconDemo.Items.Add("", 0);
lvi.SubItems.Add("Data Row 2");
lvi.SubItems.Add("Column 3 Data 2");
lvi = lvIconDemo.Items.Add("", 0);
lvi.SubItems.Add("Data Row 3");
lvi.SubItems.Add("Column 3 Data 3");
}
|
The action starts when you click on any SubItem in the ListView. The MouesUp Event gets control and is shown below.
private void lvIconDemo_MouseUp(object sender, MouseEventArgs e)
{
int selectedSubItem =
this.GetSubItem(this.lvIconDemo, new Point(e.X, e.Y));
if(selectedSubItem == -1)
this.Label1.Text = "No SubItem clicked";
else
this.Label1.Text =
String.Format("Row {1} SubItem {0} clicked",
selectedSubItem, lvIconDemo.SelectedItems[0].Index);
if(selectedSubItem==0)
{
// switch the icon
int lviRow = lvIconDemo.SelectedItems[0].Index;
if (lvIconDemo.Items[lviRow].ImageIndex==0)
lvIconDemo.Items[lviRow].ImageIndex=1;
else
lvIconDemo.Items[lviRow].ImageIndex=0;
} // if
}
|
Once the MouseUp Event receives the index of the selected SubItem, it first displays the Row and SubItem indexes in the status Label at the bottom of the form. Next, if the clicked SubItem was 0, it determnes the ImageIndex of the clicked item and toggles it between Plus and Minus, depending on the value before it was clicked.
Finally, here is the code for determining which SubItem of the ListView row was clicked. You can tell which row of the ListView was clicked by simply retrieving the Index of the first item in the ListView's SelectedItems Collection. It takes a little more to get the index of the SubItem clicked. As you can see from the code below the SendMessage API is called to retrieve a RECT structure telling the point at which the mouse is clicked. The method loops through the SubItems to find the one matchig the cursor of the mouse click.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll")]
private extern static int SendMessage(
IntPtr hWnd, int wMsg, int wParam, ref RECT lParam);
/// <summary>
/// Return -1 if invalid subitem clicked otherwise return index
/// of clicked subitem (zero based)
///
///
///
/// <returns>int
/// <remarks>
public int GetSubItem(ListView lv, Point pt)
{
const int LVM_FIRST = 0X1000;
const int LVM_GETSUBITEMRECT = LVM_FIRST + 56;
const int LVIR_BOUNDS = 0;
ListViewItem.ListViewSubItem subItem = null;
int subItemIDX = -1;
RECT lviRect;
ListViewItem lvi = lv.GetItemAt(pt.X, pt.Y);
if (lvi == null && lv.SelectedItems.Count > 0)
lvi = lv.SelectedItems[0];
if (lvi != null)
{
int sendMessageVal = 0;
for (int i = 1; i < lvi.SubItems.Count; i++)<BR>
{
subItem = lvi.SubItems[i];
lviRect = new RECT();
lviRect.Top = i;
lviRect.Left = LVIR_BOUNDS;
sendMessageVal =
SendMessage(lv.Handle,
LVM_GETSUBITEMRECT,
lvi.Index,
ref lviRect);
if (pt.X < lviRect.Left)<BR>
{
subItem = lvi.SubItems[0];
subItemIDX = 0;
break;
}
else if (pt.X >= lviRect.Left & pt.X <= lviRect.Right)<BR>
{
subItemIDX = i;
break;
}
else
subItem = null;
}
}
if (subItem == null || lvi == null)
subItemIDX = -1;
return subItemIDX;
}
|
The code shown above will work in VS2003 and VS2005. However, if you are useing VS2005, you can simplify the code by using the ListViewHitTestInfo property. If you are only interested in whether the ListViewItem or one of its SubItems was clicked, you can use the following code in the MouseUp event.
private void lvIconDemo_MouseUp(object sender, MouseEventArgs e)
{
ListViewHitTestInfo info = lvIconDemo.HitTest(e.X, e.Y);
//object subItem = info.SubItem;
//ListViewItem lvi = info.Item;
if(info.Location.ToString()=="Image")
{
// switch the icon
int lviRow = lvIconDemo.SelectedItems[0].Index;
if (lvIconDemo.Items[lviRow].ImageIndex == 0)
lvIconDemo.Items[lviRow].ImageIndex = 1;
else
lvIconDemo.Items[lviRow].ImageIndex = 0;
} // if
}
|
Of course the code shown for this MouseUp event is only concerned with switching the Icons, if an Icon has been switched. I hope this article helps someone. I plan to followup with an article that will build on this one to show you how to collapse items in a ListView.
| Ask a Question, or give your feedback on my articles or products by going to the KnowDotNet Forum or maybe even some good clean humor by clicking on My Blog. |  |
|
|