ListView SelectedIndexChanged Event no Selected Items problem - c#

I have a small C# 3.5 WinForms app I am working on that grabs the event log names from a server into a listview. When one of those items is selected, another listview is populated with the event log entries from the selected event log using the SelectedIndexChanged event by grabbing the text property of the 1st item in the SelectedItems collection as shown below.
string logToGet = listView1.SelectedItems[0].Text;
This works fine the first time, but a second selection of an event log name from the first listview fails. What is happening is the SelectedItems collection that the SelectedIndexChanged event is getting is empty so I get an ArgumentOutOfRangeException.
I am at a loss. Any ideas on what I am doing wrong or a better way to do this?

Yes, the reason is is that when you select another item, the ListView unselects the SelectedItem before selecting the new item, so the count will go from 1 to 0 and then to 1 again. One way to fix it would be to check that the SelectedItems collection contains an item before you try and use it. The way you are doing it is fine, you just need to take this into consideration
eg
if (listView1.SelectedItems.Count == 1)
{
string logToGet = listView1.SelectedItems[0].Text;
}

You should check that the SelectedItems collection has values in it before you try to retrieve values from it.
Something like:
if(listView1.SelectedItems.Count > 0)
//Do your stuff here

When you select a new item, the previous item is unselected first. Wrap your code in a quick check:
if( listView1.SelectedItems.Count > 0)
{
string logToGet = listView1.SelectedItems[0].Text;
}
This will ignore selected items changing to no selected item.

I had this problem and after spending too much time I realized that the problem is because of trying to get listView1.SelectedItems from another thread. It may be useful for others.

Related

Set a value runtime to combobox

I have a combobox populated with four items already. My app is receiving any of these four items on run time (one at a time). How can I set my comboBox with the received item (which is one of the four) on run time.
This is to make app a bit user friendly. So that user wouldnt have to select by himself. I know there can be other ways to do it but I want it to work like the way I explained in the first paragraph.
Also I have added this to make it uneditable.
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
As far as I know, there are no events fired when items are added to ComboBoxes. You are in control of when items are added, so when your code adds an item, it should fire it's own event.
However, if you know when you add the item, you can set it to equal the most recently added item like so:
comboBox1.Items.Add(item);
comboBox1.SelectedIndex = comboBox1.Items.Count - 1;
or if you may be removing some items, like so:
comboBox1.Items.Add(item);
comboBox1.SelectedItem = item;

How do I check if a selected item has changed from the previously selected item?

I have a listbox in my winform, when an item in the listbox is selected, a value is placed into a textbox in the same Form. There my many items in my listbox which when selected, i want the text box to be empty so i can pass in the new value. How do i check is if the user has clicked on something other their initial selected item? i get the currently selected item like this below:
var selectedItem = (ReportItems)listbox.selectedItem
You can use the SelectedIndexChanged event on your ListBox . You can create an event handler for this event to determine when the selected index in the ListBox has been changed. This can be useful when you need to display information in other controls based on the current selection in the ListBox. You can use the event handler for this event to load the information in the other controls.
See MSDN documentation: link
You can add a global variable for your ReportItems and call it 'selItem'.
After the user changed the selected Item you check the "new" selectedItem with the 'selItem'-variable.. i don't think that a listbox has a method that can check if the selection has changed from the previous one..
I'm not sure if there is a reason you're not leveraging the SelectionChanged event of the ListBox or not but you should be if you're not. Further, determining if it's different than the initially selected item should be pretty straight forward because you can save the initially selected item in a private variable in your form and compare every time the method handler for SelectionChanged fires.
Other than this, there's not much more I can suggest because your questions isn't terribly clear and there is no code to look at.
My solution was to always clear the textbox first. So as soon as a user selects an item in the listview, rather than populating the textbox straight away, clear the textbox before populating it.
clearText(); is called soon as a listbox item is clicked.
public void clearText()
{
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox4.Clear();
textBox5.Clear();
textBox6.Clear();
textBox7.Clear();
textBox8.Clear();
textBox9.Clear();
textBox10.Clear();
textBox11.Clear();
textBox12.Clear();
}

Unable to Select the First Item in a Listview after Item Removal

I have listview control.There is an option to remove selected items.After the user removes an item.I need to programatically select the previous item just before the removed item or the First item.I have tried
listView.Items[0].Selected = true;
listView.Select();
No item is selected or Highlighted.What could be the problem?
ListView.Select doesn't select an item in the items collection.
The right syntax is
if(this.listView1.Items.Count > 0)
{
this.listView1.Focus();
this.listView1.Items[0].Focused = true;
this.listView1.Items[0].Selected = true;
}
See MSDN here
The listView's Items Collection does not have a Select() method. Instead call the listView's Select() method. However, in most cases it should work without it.
listView.Items[0].Selected = true;
listView.Select();
By the way, "it's not working" is not a good explanation of what is causing you trouble. Be a bit more specific next time.
The code you have posted will work fine. Are you doing anything else like giving the focus to another control? The default behavior of the listView is to hide selected items when it loses focus.
Set the property HideSelection of the listView to false and see if you are able to see the selection.

ListBox.SelectedItem is null notification

I need to track current selected item in ListBox to turn off some other controls on the form when selected item become null. I try to use SelectedIndexChanged event, but it not raise when selected item is null.
Can you please advise something?
UPDATE: Selected item becomes null because i set new DataSource value with empty collection. May be it's a reason of my problem?
I need to explain. ListBox represent collection of items from database. When user add/edit/delete some item, I refresh listbox by calling this method:
private void RefreshList()
{
lbParts.DataSource = this.database.Fetch<part>(string.Empty);
}
It fetched all items from database, convert it to List<part> collection and set as ListBox DataSource.
That is incorrect. SelectedIndexChanged is raised when SelectedItem becomes null. In this case, SelectedIndex will be -1.
EDIT: you are indeed correct that when you change DataSource, you don't get SelectedIndexChanged. I would recommend explicitly setting SelectedIndex=-1 immediately before anytime you change DataSource
Perhaps handle the DataSourceChanged event as well? If the choices available in the listbox change, then I assume this is reason to perform a refresh on the forms avialable controls?

What exactly is ListView.RetrieveVirtualItem Event - C#

With respect to a Virtual ListView control in a Winforms App, what are ALL the functions of RetrieveVirtualItem event?
Scenario: There is a Dictionary object which acts as my ListView cache. And its items are displayed on the ListView. On click of a column, the cache dictionary is sorted in memory and the ListView is Refresh()ed. The effect on UI, the ListView is sorted well. :)
But I want to understand what the role of RetrieveVirtualItem Event is, which gets triggered on Refresh().
In the RetrieveVirtualItem event handler [ Someone else's code, :( ], following are done:
Based on RetrieveVirtualItemEventArgs.ItemIndex, get the message from Cache
Set RetrieveVirtualItemEventArgs.Item = retreived item above
It appears that what's done in the event handler is important because, if I take it out, ListView cries. What is the significance of this event?
EDIT
Or let me re-phrase the question... My concern is, Why, after Sorting (and RetrieveVirtualItem event handler), the selected item remains at the location where it was before sorting. I.e, If I select item #5 and sort, and if sorting makes this item as the last item, I would prefer the LAST item to be selected after Sort. But in my case 5th item is selected after sort. So what is the default behavior of RetrieveVirtualItem WRT selected item?
A virtual ListView should only call RetreiveVirtualItem for the rows currently visible on the screen.
As you navigate in the ListView, for example, you press the page down key, the ListView will calculate what should now be the index of the top row and will then call RetrieveVirtualItem so that your code can provide the item to use at each row index.
Unless you cache or otherwise store the items you are providing via RetrieveVirtualItem, they will no longer exist once they are scrolled out of the listview.
This is what the Virtual in VirtualListView means - there aren't any real rows, the rows are virtual. That is how it could display a list containing hundreds of thousands of rows - because it will ever only actually contain how ever many rows are visible on screen.
In effect, the ListView is like a window that is moving up and down your internal list of data - the RetreiveVirtualItem method is what it calls to move items into that window as it moves along. It says, hey I just moved to row 15 - give me the item for that row. It will proceed to call RetreiveVirtualItem for each row index which would be visible. If the ListView was 5 rows in height on the screen, you would receive 5 calls to RetrieveVirtualItem - even if the actual data backing the listview had 3000 items. Each time the top row of the ListView changed (because of navigation), you would receive 5 calls to RetrieveVirtualItem (this is not always the case, but it is the right idea - for example, if you scroll down one row, it will simply ask you for the new last row - it will also simply discard the data that was used for the old top row that scrolled out of view).
I guess it might be even easier to explain if we assume the ListView was only one row high on the display (meaning only a single row is ever actually visible on the screen) - as you move the ListView up and down your list of data (i.e. the user navigates the ListView), it would call RetrieveVirtualItem exactly one time every time it moves to a new row.
Hope that helps...
Good Luck
Virtual listviews only deal with indices. So, if the 5th item is selected before the sort, the 5th item will still be selected after the sort. The control itself has no way of knowing that the data that used to be on the 5th row is now on the first row.
You will have to program that for yourself in your sorting method:
remember which items were selected (remember: you can't use SelectedItems property when in virtual mode)
do the sort
find the indices of the previously selected item now live
select those indices
You can see all this in action in ObjectListView -- a wrapper around a standard .NET ListView.
The RetrieveVirtualItem event is only used when the ListView is put into virtual mode. Rather than retaining ListViewItems in the Items collection (as when not in virtual mode), it creates the ListViewItems dynamically, when needed.
If you don't handle the RetrieveVirtualItem event then no ListViewItems will be added to your ListView. I've attached some sample code for a typical method written to handle the event:
//Dynamically returns a ListViewItem with the required properties; in this case, the square of the index.
void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
//Check if cache has been instantiated yet, and if so, whether the item corresponding to the index requested has been added to the cache already
if (myCache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + myCache.Length)
{
//Return cached item for index
e.Item = myCache[e.ItemIndex - firstItem];
}
else
{
//When item not in cache (or cache not available) return a new ListViewItem
int x = e.ItemIndex * e.ItemIndex;
e.Item = new ListViewItem(x.ToString());
}
}
This example is taken from MSDN (http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode(v=vs.90).aspx) where further details can be found.

Categories