Question

Using Visual Studio 2008, .Net 3.5

I have a ListView loaded with a bunch of items. I have a right-click popup for removing an item. After removal of an item, I redraw the list view by re-accessing my primary data, and reset the selected item. However, the selected item does not show as selected.

An idea of the code:

public ListView m_lv;  
public MyDataCollection m_Data;  // Has a function to get data based on a tag.  

public void RemoveEventHandler(object sender, EventArgs e)  
{  
  int iSelectedItem= m_lv.FocusedItem.Index;

  int iDataIndexToRemove= m_Data.GetIndexOf(m_lv.FocusedItem.Tag.ToString());  

  m_Data.RemoveAt(iDataIndexToRemove);  // Remove the item.  

  if(0 != m_lv.Items.Count)  
  {  
    if(iSelectedItem == m_Data.Items.Count)  // Removed last.  
      iSelectedItem= m_Data.Items.Count - 1;  
  }

  m_lv.Items.Clear();  // Clear the list view items.  

  // Completely rebuild the list view.  
  foreach(MyData md in m_Data)  
  {  
    ListViewItem lvi= new ListViewItem(md.Column0.ToString());  
    lvi.SubItems.Add(md.Column1.ToString());  
    lvi.SubItems.Add(md.Column3.ToString());  
    lvi.SubItems.Add(md.Column4.ToString());  

    m_lv.Items.Add(lvi);  
  }  

  // Set up tags, column sizes, etc.  

  if(0 != m_lv.Items.Count)  
    m_lv.Items[iSelectedItem].Selected= true;  // Set the selection.      
}  

If I do something like the above, the selected item never shows visually as selected (no background color change) unless I re-size a column or sort. Then it shows as selected. However, if I use the debugger or add a button to use a message box to show me selected items, the item knows it is selected.

I know it is some kind of refresh/drawing problem - any ideas?

Was it helpful?

Solution 4

It ended up being pretty easy:

// Figure out index of item to remove, iRemoved, do some work....  

m_lv.Items.RemoveAt(iRemoved);  
m_lv.Refresh();

// Figure out what is left so new selection, iNewSelection, can be set....
m_lv.Items[iNewSelection].Selected = true;  

Forgot I had not updated this post!

OTHER TIPS

Sounds like your ListView doesn't have focus as a result of your right-click popup, and has HideSelection set to true. This would mean that while your item is selected, WinForms isn't displaying it. Turn HideSelection off first to check, then you'll need some code to set focus back to the listview.

In addition:

  1. If you use ListView.Items.Clear(), you won't lose the columns and therefore have to re-add them each time (which would irritate users who have resized the column headers).
  2. Don't do the whole clear-and-refresh thing. Set each ListViewItem's Name property as your primary key, then you can do ListViewItem liToRemove = listView[name];

After setting the selection try calling Invalidate method on ListView.

Use this:

m_lv.BeginUpdate();

// Add the items

m_lv.EndUpdate();
//
if(0 != m_lv.Items.Count)  
    m_lv.Items[iSelectedItem].Selected= true;  // Set the selection.   

Do not call 'Invalidate', using the Begin/End Update should do the prevention of the flicker and refresh...

Edit: To explain my reasoning behind the statement... BeginUpdate freezes any WM_PAINT messages...EndUpdate unfreezes WM_PAINT, this makes the adding items to the list appear much quicker, and anyway, after a call to EndUpdate, it will refresh! The selection can be either way, I prefer to put it outside of EndUpdate...that's my opinion...Invalidate generates WM_PAINT message but is not necessarily processed straight away...It would not be advisable to be calling Invalidate() in the loop where the items are being added as the refresh would slow down!

Hope this helps, Best regards, Tom.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top