0

I have a treeview which is in detail view. listview is populated with items and subitems which are in pair of 4 rows are related together. I have set Name property of each of rows in this 4 items the same.

What I am looking for, is when user selects a row, all the 4 rows which have similar Name propety be selected (hilighted) automatically.

What I have done so far is in below, but it does not compile!

private void resultSheet_SelectedIndexChanged(object sender, EventArgs e)
{
    string name = resultSheet.SelectedItems[0].Name.ToString();

    ListView.ListViewItemCollection items = new ListView.ListViewItemCollection(resultSheet);

    foreach (ListViewItem item in resultSheet.Items)
    {
        if (item.Name.ToString() == name) 
        {
            items.Add(item);
        }
    }

    resultSheet.SelectedItems = items; //Does not compile 

}
Dumbo
  • 13,555
  • 54
  • 184
  • 288
  • [ListView.SelectedItems](http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.selecteditems.aspx) is readonly. – Tim Schmelter Dec 10 '11 at 23:57

2 Answers2

2

ListView.SelectedItems is readonly.

if(resultSheet.SelectedItems.Count >= 1)
{
    string name = resultSheet.SelectedItems[0].Name.ToString();
    foreach (ListViewItem item in resultSheet.Items)
    {
        item.Selected = item.Name.ToString() == name; 
    }
}

Edit: Acccording to your comment on the other answer: Make sure that SelectedItems.Count >= 1 before accessing the item at index 0, because "No selection" is also a possible state. When you select another item, the ListView unselects the SelectedItem before selecting the new item

If you want to avoid unnecessary SelectedIndexChanged events, try Robert's Timer-ListView approach or this Application.Idle approach(VB.NET but easy to convert) what is used by ObjectListView under the hood to prevent from multiple events triggering.

Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

Just change your method in this way:

 bool inAction = false;

 private void resultSheet_SelectedIndexChanged(object sender, EventArgs e)
 {
     if (inAction || (resultSheet.SelectedItems.Count == 0))
     {
         return;
     }
     inAction = true;
     string name = resultSheet.SelectedItems[0].Name;

     foreach (ListViewItem item in resultSheet.Items)
     {
         if (item.Name.ToString() == name)
         {
             item.Selected = true;
         }
     }
     inAction = false;
 } 

Edit: Or if you prefer LINQ, do it like this:

 bool inAction = false;

 private void resultSheet_SelectedIndexChanged(object sender, EventArgs e)
 {
     if (inAction || (resultSheet.SelectedItems.Count == 0))
     {
         return;
     }
     inAction = true;
     string name = resultSheet.SelectedItems[0].Name;

     foreach (ListViewItem item in resultSheet.Items.OfType<ListViewItem>().Where(item => item.Name == name))
     {
         item.Selected = true;
     }
     inAction = false;
 } 
Fischermaen
  • 12,238
  • 2
  • 39
  • 56
  • Thanks, this works. but only in the first mouseclick on a row. the next time it fails and debugger says `InvalidArgument=Value of '0' is not valid for 'index'` for the `string name = resultSheet.SelectedItems[0].Name;` line. mind to fix that also ?! – Dumbo Dec 11 '11 at 00:01
  • @Sean: edited [my answer](http://stackoverflow.com/a/8460885/284240) to take your comment into account. – Tim Schmelter Dec 11 '11 at 00:09
  • @TimSchmelter: Oops, missed that point, changed it in my answer too. – Fischermaen Dec 11 '11 at 00:12