views:

706

answers:

3

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?

+2  A: 

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];
Neil Barnwell
You were right - the "HideSelection" property was set to "false". It does seem to be a focus problem.Note I am using ListView.Items.Clear() so that I only clear the items, not the columns.I am not sure what you are getting at with the ListViewItem Name property. I think you mean just remove the item from the view, and the corresponding datum from the data collection. I was originally doing that, but ran into the refresh problem, and decided to do the whole items redraw.Thanks for he help!
GTAE86
A: 

After setting the selection try calling Invalidate method on ListView.

Jacob Seleznev
A: 

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.

tommieb75
What's wrong with Invalidate?And how does Begin/EndUpdate help to solve refresh problem? Shouldn't then EndUpdate be after setting the selection?
Jacob Seleznev