Select index from listview - c#

I'm having some problem to get the index of the selected row in a listview. I wonder why this code isn't working? I get a red line below the SelectedIndex
private void lvRegAnimals_SelectedIndexChanged(object sender, EventArgs e)
{
int index = lvRegAnimals.SelectedIndex;
string specialData = motelManager.GetInfoFromList(index);
UppdateSpecialData(specialData);
}
Help is preciated. Thanks!
EDIT:
For some strange reason I get two messages when I click on one of the lines in the listView!? First I get the previous number and then the number for the last clicked line. What could be wrong?
private void lvRegAnimals_SelectedIndexChanged(object sender, EventArgs e)
{
int index = lvRegAnimals.FocusedItem.Index;
MessageBox.Show(Convert.ToString(index));
}
It's working now when I added a check like this:
if(lvRegAnimals.SelectedIndices.Count > 0)

Because ListView doesn't contain any SelectedIndex, instead there is a property of SelectedIndices.
var indices = lvRegAnimals.SelectedIndices;
//indices[0] you can use that to access the first selected index
ListView.SelectedIndices
When the MultiSelect property is set to true, this property returns a
collection containing the indexes of all items that are selected in
the ListView. For a single-selection ListView, this property returns a
collection containing a single element containing the index of the
only selected item in the ListView.

private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
// Acquire SelectedItems reference.
var selectedItems = listView1.SelectedItems;
if (selectedItems.Count > 0)
{
// Display text of first item selected.
this.Text = selectedItems[0].Text;
}
else
{
// Display default string.
this.Text = "Empty";
}
}

Try :
listView1.FocusedItem.Index
This give you the index of the selected row.

There is another thread like this one, but here it goes again.
It can return NULL. Also the SelectedIndexChanged event can be FIRED TWICE. And the first time, there nothing selected yet.
So the only safe way to find it is like this:
private void lv1_SelectedIndexChanged(object sender, EventArgs e)
{
if (lv1.FocusedItem == null) return;
int p = lv1.FocusedItem.Index;
... now int p has the correct value...

The ListView is a darn hassle to work with sometimes.
A simple solution i've used is a for loop that checks for the
selected Item.
I've put my solution in the "When index change trigger" within the ListView.
Example:
int sel_item = 0; //an int to store the selected item index.
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Selected == true)
{
sel_item = i;
}
}
}
This would ofcourse only work correctly with the "Multiselection" option set as false.

Related

Error when selecting second item from ListView C#

I have a list view with the multiselect property set to false. When the user clicks on it, I take the NAME property of the list view item and convert it to a decimal then feed that to a method that loads the correct record.
The code below works perfectly when I select one item regardless of how many items are in the list and regardless of which item I select.
private void ListInstruments_SelectedIndexChanged(object sender, EventArgs e)
{
ListViewItem selection = listInstruments.SelectedItems[0];
if (selection != null)
{
string strSelection = selection.Name;
SelectedInstrumentID = Convert.ToDecimal(strSelection);
LoadSelectedInstrument();
}
}
When I make a second selection (not multi-select, but a different selection from the listbox) I get an error referencing listInstruments.SelectedItems[0].
System.ArgumentOutOfRangeException Message=InvalidArgument=Value of
'0' is not valid for 'index'. Parameter name: index
Source=System.Windows.Forms
Any help would be appreciated.
It's possible, that no items are selected, and thus list.SelectedItems is empty; you are tring to get 0th item from the empty collection and thus have the exception thrown. The quick patch is
// instead of original
// ListViewItem selection = listInstruments.SelectedItems[0];
ListViewItem selection = list.SelectedItems.Count > 0
? listInstruments.SelectedItems[0] // the collection has at least one item
: null; // if the collection is empty
Or we can check if we have a selection and return when there's none
private void ListInstruments_SelectedIndexChanged(object sender, EventArgs e)
{
if (list.SelectedItems.Count <= 0)
return;
listViewItem selection = listInstruments.SelectedItems[0];
string strSelection = selection.Name;
SelectedInstrumentID = Convert.ToDecimal(strSelection);
LoadSelectedInstrument();
}

Remove items from ListBox if item exists in another ListBox

I am trying to remove numerical items from a ListBox if those values exist in another ListBox. My code does not seem to work and I could not locate any help online. ListBox1 is populated by Array and ListBox2 is populated from a DataSet table (fyi).
Also for reference: I'm not adding and items to a listbox or selecting...simply just want to compare both and remove ListBox2 items from ListBox1 if they exist all automatically with a press of a button. Thank you,
private void button1_Click(object sender, EventArgs e)
{
foreach (int item in listBox1.Items)
{
if (listBox2.Items.Contains(item))
{
listBox1.Items.Remove(item);
}
}
}
Well you're only referencing one list box in your code - I suspect you would want:
private void button1_Click(object sender, EventArgs e) {
foreach (int item in listBox1.Items)
{
if (listBox2.Items.Contains(item)) // notice change of reference
{
listBox1.Items.Remove(item);
}
}
However that would cause an error since you're modifying the ListBox while you're iterating over it's items. One way to safely remove items it to iterate backwards over the colection:
for (int i = listBox1.Items.Count - 1; i >= 0; i--)
{
int item = listBox1.Items[i];
if (listBox2.Items.Contains(item)) // notice change of reference
{
listBox1.Items.RemoveAt(i);
}
}
#D Stanley
Thank you for your help and explanation. #Yuriy - Thank you for the clarification, the
i >= 0
works great. I also converted to listbox to int32. Below is the fully working code:
private void button1_Click(object sender, EventArgs e)
{
for (int i = listBox1.Items.Count - 1; i>= 0; i--)
{
int item = Convert.ToInt32(listBox1.Items[i]);
if (listBox2.Items.Contains(item))
{
listBox1.Items.Remove(item);
}
}
}

Remove items from ListBox when DataSource is set

See I have a HashSet with several values, this values can contain for example numbers like 4141234567, 4241234567, 4261234567 and so on. I put a radioButton1 in my UserControl and I want when I click this just the numbers with 414 and 424 remains on my ListBox, for that I wrote this code:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
var bdHashSet = new HashSet<string>(bd);
if (openFileDialog1.FileName.ToString() != "")
{
foreach (var item in bdHashSet)
{
if (item.Substring(1, 3) != "414" || item.Substring(1, 3) != "424")
{
listBox1.Items.Remove(item);
}
}
}
}
But when I run the code I get this error:
Items collection cannot be modified when the DataSource property is set.
What is the proper way to remove the non wanted items from the list without remove them from the HashSet? I'll add later a optionButton for numbers that begin with 0416 and 0426 and also a optionButton to fill the listBox with original values, any advice?
try
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
var bdHashSet = new HashSet<string>(bd);
listBox1.Datasource = null;
listBox1.Datasource = bdHashSet.Where(s => (s.StartsWith("414") || s.StartsWith("424"))).ToList();
}
Try this:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
var bdHashSet = new HashSet<string>(bd);
listBox1.Datasource = bdHashSet.Select(s => (s.Substring(1, 3) == "414" || s.Substring(1, 3) == "424"));
//After setting the data source, you need to bind the data
listBox1.DataBind();
}
I think that you can select the elements with linq and then reassign the listBox with the result. In that way you dont need to remove elements from the list and you can keep the elements of the HashSet.
You can use BindingSource object. Bind it with DataSource and then use the RemoveAt() method.
Try this :
DataRow dr = ((DataRowView)listBox1.SelectedItem).Row;
((DataTable)listBox1.DataSource).Rows.Remove(dr);

How to pass a text while firing an event?

I need to pass a checkeditem of a checklistbox while firing an event from a dynamic checklistbox. The code snippet is provided below with comments...
I'm facing an issue with the same piece of code. On mouse double click event its throwing an exception saying IndexoutofRange. Its working fine with the index value 0.Please help 2 solve me both.
private void clbTables_MouseDoubleClick(object sender, MouseEventArgs e)
{
int indexofselectedtable;
indexofselectedtable = Convert.ToInt32(clbTables.SelectedIndex);
if (clbTables.CheckedItems.Count != 0)
{
Metadata metadataobj = new Metadata(dbProperties);
DBList = metadataobj.GetColumns(clbTables.CheckedItems[indexofselectedtable].ToString()); // This throws an error on checking an item of index>0.
for (int j = 0; j < DBList.Count; j++)
{
chklistcolumns.Name = "chklist" + j++;
chklistcolumns.Items.Add(DBList.ElementAt(j));
}
this.Controls.Add(chklistcolumns);
chklistcolumns.ItemCheck += new ItemCheckEventHandler(OnCheckListBoxItemCheck);
}
}
private void OnCheckListBoxItemCheck(object sender, ItemCheckEventArgs args) //need to pass the tablename which can be got from the object clbTables
{
Columns columnobj = new Columns();
columnobj.ColumnName = this.Text;
columnobj.Id = this.Name;
columnobj.TableName= // need to get the tablename from the object clbtables
}
I think I see what the issue here is, you are trying to match the selected index of your CheckedListBox with an index in the CheckedItems collection, but it doesn't work that way.
Consider this: you have 10 items in your CheckedListBox, and three of them are checked. That gives you .Items[10] and .CheckedItems[3]. If then you double click on the 7th item in the CheckedListBox, your SelectedIndex will be 6, but there will only be three items in the CheckedItems collection. So when you try to read clbTables.CheckedItems[6] you are going to be outside of the range of that collection.
clbTables.CheckedItems is another collection. You can't use clbTables.SelectedIndex in it.
Why not just to use SelectedValue property?

How to remove all ListBox items?

I created two RadioButton (Weight and Height). I will do switch between the two categories. But the they share the same ListBox Controllers (listBox1 and listBox2).
Is there any good method to clear all the ListBox items simpler? I didn't find the removeAll() for ListBox. I don't like my complex multi-lines style which I posted here.
private void Weight_Click(object sender, RoutedEventArgs e)
{
// switch between the radioButton "Weith" and "Height"
// Clear all the items first
listBox1.Items.Remove("foot");
listBox1.Items.Remove("inch");
listBox1.Items.Remove("meter");
listBox2.Items.Remove("foot");
listBox2.Items.Remove("inch");
listBox2.Items.Remove("meter");
// Add source units items for listBox1
listBox1.Items.Add("kilogram");
listBox1.Items.Add("pound");
// Add target units items for listBox2
listBox2.Items.Add("kilogram");
listBox2.Items.Add("pound");
}
private void Height_Click(object sender, RoutedEventArgs e)
{
// switch between the radioButton "Weith" and "Height"
// Clear all the items first
listBox1.Items.Remove("kilogram");
listBox1.Items.Remove("pound");
listBox2.Items.Remove("kilogram");
listBox2.Items.Remove("pound");
// Add source units items for listBox1
listBox1.Items.Add("foot");
listBox1.Items.Add("inch");
listBox1.Items.Add("meter");
// Add target units items for listBox2
listBox2.Items.Add("foot");
listBox2.Items.Add("inch");
listBox2.Items.Add("meter");
}
isn't the same as the Winform and Webform way?
listBox1.Items.Clear();
I think it would be better to actually bind your listBoxes to a datasource, since it looks like you are adding the same elements to each listbox. A simple example would be something like this:
private List<String> _weight = new List<string>() { "kilogram", "pound" };
private List<String> _height = new List<string>() { "foot", "inch", "meter" };
public Window1()
{
InitializeComponent();
}
private void Weight_Click(object sender, RoutedEventArgs e)
{
listBox1.ItemsSource = _weight;
listBox2.ItemsSource = _weight;
}
private void Height_Click(object sender, RoutedEventArgs e)
{
listBox1.ItemsSource = _height;
listBox2.ItemsSource = _height;
}
Write the following code in the .cs file:
ListBox.Items.Clear();
while (listBox1.Items.Count > 0){
listBox1.Items.Remove(0);
}
You should be able to use the Clear() method.
I made on this way, and work properly to me:
if (listview1.Items.Count > 0)
{
for (int a = listview1.Items.Count -1; a > 0 ; a--)
{
listview1.Items.RemoveAt(a);
}
listview1.Refresh();
}
Explaining: using "Clear()" erases only the items, do not
removes then from object, using RemoveAt() to removing an item of beginning position
just realocate the others [if u remove item[0], item[1] turns into [0] triggering a new internal event],
so removing from the ending no affect de others position,
its a Stack behavior, this way we can Stack over all items, reseting the object.
VB
ListBox2.DataSource = Nothing
C#
ListBox2.DataSource = null;

Categories