Error removing last item from a ListBox

G

Guest

I'm have a sample form, with a ListBox and a Remove button, I'm doing data
binding to a custom collection, everything is working find, I can bind the
list box, I can see the items appear on the list, I can remove items from the
list, BUT my problem is when I attempt to remove the last item on the list, I
get the following error:

System.ArgumentOutOfRangeException: Specified argument was out of the range
of valid values. Parameter name: Index was out of range. Must be
non-negative and less than the size of the collection
at
System.Collections.CollectionBase.System.Collections.IList.get_Item(Int32
index)
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32
newPosition, Boolean validating, Boolean endCurrentEdit, Boolean
firePositionChange, Boolean pullData)
at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
at System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ListBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ListBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

This is the source code I'm using (C#):

Collection.cs
public class Collection : System.Collections.CollectionBase
{
private Collection()
{
}
public static Collection NewCollection()
{
return new Collection();
}
public void Remove(CollectionItem item)
{
if (this.List.Contains(item))
this.List.Remove(item);
}
public int Add(string displayText, string valueText)
{
return this.List.Add(CollectionItem.NewCollectionItem(displayText,
valueText));
}
public CollectionItem this[int index]
{
get{return (CollectionItem)this.List[index];}
}
}

CollectionItem.cs
public class CollectionItem
{
private string _displayText = string.Empty;
private string _valueText = string.Empty;

public string DisplayText
{
get{return this._displayText;}
set{this._displayText = value;}
}
public string ValueText
{
get{return this._valueText;}
set{this._valueText = value;}
}
private CollectionItem(string displayText, string valueText)
{
this._displayText = displayText;
this._valueText = valueText;
}
public static CollectionItem NewCollectionItem(string displayText, string
valueText)
{
return new CollectionItem(displayText, valueText);
}
}

Form code:
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox lisItems;
private Collection items = Collection.NewCollection();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

items.Add("One", "1");
items.Add("Two", "2");
items.Add("Three", "3");
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;

CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;

items.Remove(item);
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";

this.lisItems.ResumeLayout();
}
}

NOTE: I just paste the relevant code!


Upon clicking the Remove button, I'm removing the selected item from the
collection and re-binding the collection. I can remove any element, BUT ONLY
THE LAST ONE GIVES ME THE ERROR.



Thanks in advance for your help
 
J

Jc Morin

I've run your code and it work here! ahaha, well there is only one error and
it's not the one you paste. I get an error un DataSource on the last item.
The collection is empty and can't found display property...

Here is the changed I made to the remove button.
private void button1_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;
CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;
items.Remove(item);
if (items.Count == 0)
{
this.lisItems.Items.Clear();
}
else
{
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
this.lisItems.ResumeLayout();
}


--------------------------
Jean-Claude Morin, MCP
Software Developer
2k1Soft/kCentric, Canada


Luis Fajardo said:
I'm have a sample form, with a ListBox and a Remove button, I'm doing data
binding to a custom collection, everything is working find, I can bind the
list box, I can see the items appear on the list, I can remove items from the
list, BUT my problem is when I attempt to remove the last item on the list, I
get the following error:

System.ArgumentOutOfRangeException: Specified argument was out of the range
of valid values. Parameter name: Index was out of range. Must be
non-negative and less than the size of the collection
at
System.Collections.CollectionBase.System.Collections.IList.get_Item(Int32
index)
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32
newPosition, Boolean validating, Boolean endCurrentEdit, Boolean
firePositionChange, Boolean pullData)
at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
at System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ListBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ListBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

This is the source code I'm using (C#):

Collection.cs
public class Collection : System.Collections.CollectionBase
{
private Collection()
{
}
public static Collection NewCollection()
{
return new Collection();
}
public void Remove(CollectionItem item)
{
if (this.List.Contains(item))
this.List.Remove(item);
}
public int Add(string displayText, string valueText)
{
return this.List.Add(CollectionItem.NewCollectionItem(displayText,
valueText));
}
public CollectionItem this[int index]
{
get{return (CollectionItem)this.List[index];}
}
}

CollectionItem.cs
public class CollectionItem
{
private string _displayText = string.Empty;
private string _valueText = string.Empty;

public string DisplayText
{
get{return this._displayText;}
set{this._displayText = value;}
}
public string ValueText
{
get{return this._valueText;}
set{this._valueText = value;}
}
private CollectionItem(string displayText, string valueText)
{
this._displayText = displayText;
this._valueText = valueText;
}
public static CollectionItem NewCollectionItem(string displayText, string
valueText)
{
return new CollectionItem(displayText, valueText);
}
}

Form code:
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox lisItems;
private Collection items = Collection.NewCollection();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

items.Add("One", "1");
items.Add("Two", "2");
items.Add("Three", "3");
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;

CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;

items.Remove(item);
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";

this.lisItems.ResumeLayout();
}
}

NOTE: I just paste the relevant code!


Upon clicking the Remove button, I'm removing the selected item from the
collection and re-binding the collection. I can remove any element, BUT ONLY
THE LAST ONE GIVES ME THE ERROR.



Thanks in advance for your help
 
G

Guest

Jc, thanks for responding. Just want to clarify that the error doesn't ocurr
right after clicking remove for the last item, you need to click any other
item on the list, after removing the last one to get the error.

Here are the steps to replicate it:

1.Be sure you have multiple items displayed on the list box
2.Select the last item on the list box
3.Click the remove button
4.The remove button actually removes the item from the collection and binds
the control again so you don't see the last item anymore
5.You will noticed that no item is currently selected on the list
6.Now select any item on the list, there is where you get the error

Please confirm that this is happening to you, I test this code in multiple
computers with different type of custom collections, I'm using XP SP2 with
VS2003 & .NET 1.1.

Let me know,
Thanks


Luis Fajardo said:
I'm have a sample form, with a ListBox and a Remove button, I'm doing data
binding to a custom collection, everything is working find, I can bind the
list box, I can see the items appear on the list, I can remove items from the
list, BUT my problem is when I attempt to remove the last item on the list, I
get the following error:

System.ArgumentOutOfRangeException: Specified argument was out of the range
of valid values. Parameter name: Index was out of range. Must be
non-negative and less than the size of the collection
at
System.Collections.CollectionBase.System.Collections.IList.get_Item(Int32
index)
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32
newPosition, Boolean validating, Boolean endCurrentEdit, Boolean
firePositionChange, Boolean pullData)
at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
at System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ListBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ListBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

This is the source code I'm using (C#):

Collection.cs
public class Collection : System.Collections.CollectionBase
{
private Collection()
{
}
public static Collection NewCollection()
{
return new Collection();
}
public void Remove(CollectionItem item)
{
if (this.List.Contains(item))
this.List.Remove(item);
}
public int Add(string displayText, string valueText)
{
return this.List.Add(CollectionItem.NewCollectionItem(displayText,
valueText));
}
public CollectionItem this[int index]
{
get{return (CollectionItem)this.List[index];}
}
}

CollectionItem.cs
public class CollectionItem
{
private string _displayText = string.Empty;
private string _valueText = string.Empty;

public string DisplayText
{
get{return this._displayText;}
set{this._displayText = value;}
}
public string ValueText
{
get{return this._valueText;}
set{this._valueText = value;}
}
private CollectionItem(string displayText, string valueText)
{
this._displayText = displayText;
this._valueText = valueText;
}
public static CollectionItem NewCollectionItem(string displayText, string
valueText)
{
return new CollectionItem(displayText, valueText);
}
}

Form code:
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox lisItems;
private Collection items = Collection.NewCollection();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

items.Add("One", "1");
items.Add("Two", "2");
items.Add("Three", "3");
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;

CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;

items.Remove(item);
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";

this.lisItems.ResumeLayout();
}
}

NOTE: I just paste the relevant code!


Upon clicking the Remove button, I'm removing the selected item from the
collection and re-binding the collection. I can remove any element, BUT ONLY
THE LAST ONE GIVES ME THE ERROR.



Thanks in advance for your help
 
J

Jc Morin

Ok, I can confirm you that your situation is reproductable.
It seems that your collection have no at all effets on that. I even try a
simple ArrayList and the problem is the same.
I've also try to remove with SelectedIndex and RemoveAt...

I came to the conclusion that for some unknown reason the DataSource stuff
do not works as I expected.
I think that internaly the control keep a reference to the list and we
modifiy it and we scew up everything.

Here is my suggestion / fix from your isssue.

Replace
--------------------
this.lisItems.DataSource = items
-----------------
With
--------------------
foreach (CollectionItem oItem in items)
{
this.lisItems.Items.Add(oItem);
}
----------------------
in both the contructor and the button handling.

The button code should look like this.
--------------------------------
private void button1_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;
CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
items.Remove(this.lisItems.SelectedItem);
this.lisItems.Items.Clear();
foreach (CollectionItem oItem in items)
{
this.lisItems.Items.Add(oItem);
}
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
this.lisItems.ResumeLayout();
}
----------------------


--------------------------
Jean-Claude Morin, MCAD
Software Developer
2k1Soft/kCentric, Canada


Luis Fajardo said:
Jc, thanks for responding. Just want to clarify that the error doesn't ocurr
right after clicking remove for the last item, you need to click any other
item on the list, after removing the last one to get the error.

Here are the steps to replicate it:

1.Be sure you have multiple items displayed on the list box
2.Select the last item on the list box
3.Click the remove button
4.The remove button actually removes the item from the collection and binds
the control again so you don't see the last item anymore
5.You will noticed that no item is currently selected on the list
6.Now select any item on the list, there is where you get the error

Please confirm that this is happening to you, I test this code in multiple
computers with different type of custom collections, I'm using XP SP2 with
VS2003 & .NET 1.1.

Let me know,
Thanks


Luis Fajardo said:
I'm have a sample form, with a ListBox and a Remove button, I'm doing data
binding to a custom collection, everything is working find, I can bind the
list box, I can see the items appear on the list, I can remove items from the
list, BUT my problem is when I attempt to remove the last item on the list, I
get the following error:

System.ArgumentOutOfRangeException: Specified argument was out of the range
of valid values. Parameter name: Index was out of range. Must be
non-negative and less than the size of the collection
at
System.Collections.CollectionBase.System.Collections.IList.get_Item(Int32
index)
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32
newPosition, Boolean validating, Boolean endCurrentEdit, Boolean
firePositionChange, Boolean pullData)
at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
at System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ListBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ListBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

This is the source code I'm using (C#):

Collection.cs
public class Collection : System.Collections.CollectionBase
{
private Collection()
{
}
public static Collection NewCollection()
{
return new Collection();
}
public void Remove(CollectionItem item)
{
if (this.List.Contains(item))
this.List.Remove(item);
}
public int Add(string displayText, string valueText)
{
return this.List.Add(CollectionItem.NewCollectionItem(displayText,
valueText));
}
public CollectionItem this[int index]
{
get{return (CollectionItem)this.List[index];}
}
}

CollectionItem.cs
public class CollectionItem
{
private string _displayText = string.Empty;
private string _valueText = string.Empty;

public string DisplayText
{
get{return this._displayText;}
set{this._displayText = value;}
}
public string ValueText
{
get{return this._valueText;}
set{this._valueText = value;}
}
private CollectionItem(string displayText, string valueText)
{
this._displayText = displayText;
this._valueText = valueText;
}
public static CollectionItem NewCollectionItem(string displayText, string
valueText)
{
return new CollectionItem(displayText, valueText);
}
}

Form code:
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox lisItems;
private Collection items = Collection.NewCollection();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

items.Add("One", "1");
items.Add("Two", "2");
items.Add("Three", "3");
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;

CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;

items.Remove(item);
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";

this.lisItems.ResumeLayout();
}
}

NOTE: I just paste the relevant code!


Upon clicking the Remove button, I'm removing the selected item from the
collection and re-binding the collection. I can remove any element, BUT ONLY
THE LAST ONE GIVES ME THE ERROR.



Thanks in advance for your help
 
G

Guest

Jc, thanks for your time, I'm going to use your suggestion.

Jc Morin said:
Ok, I can confirm you that your situation is reproductable.
It seems that your collection have no at all effets on that. I even try a
simple ArrayList and the problem is the same.
I've also try to remove with SelectedIndex and RemoveAt...

I came to the conclusion that for some unknown reason the DataSource stuff
do not works as I expected.
I think that internaly the control keep a reference to the list and we
modifiy it and we scew up everything.

Here is my suggestion / fix from your isssue.

Replace
--------------------
this.lisItems.DataSource = items
-----------------
With
--------------------
foreach (CollectionItem oItem in items)
{
this.lisItems.Items.Add(oItem);
}
----------------------
in both the contructor and the button handling.

The button code should look like this.
--------------------------------
private void button1_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;
CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
items.Remove(this.lisItems.SelectedItem);
this.lisItems.Items.Clear();
foreach (CollectionItem oItem in items)
{
this.lisItems.Items.Add(oItem);
}
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
this.lisItems.ResumeLayout();
}
----------------------


--------------------------
Jean-Claude Morin, MCAD
Software Developer
2k1Soft/kCentric, Canada


Luis Fajardo said:
Jc, thanks for responding. Just want to clarify that the error doesn't ocurr
right after clicking remove for the last item, you need to click any other
item on the list, after removing the last one to get the error.

Here are the steps to replicate it:

1.Be sure you have multiple items displayed on the list box
2.Select the last item on the list box
3.Click the remove button
4.The remove button actually removes the item from the collection and binds
the control again so you don't see the last item anymore
5.You will noticed that no item is currently selected on the list
6.Now select any item on the list, there is where you get the error

Please confirm that this is happening to you, I test this code in multiple
computers with different type of custom collections, I'm using XP SP2 with
VS2003 & .NET 1.1.

Let me know,
Thanks


Luis Fajardo said:
I'm have a sample form, with a ListBox and a Remove button, I'm doing data
binding to a custom collection, everything is working find, I can bind the
list box, I can see the items appear on the list, I can remove items from the
list, BUT my problem is when I attempt to remove the last item on the list, I
get the following error:

System.ArgumentOutOfRangeException: Specified argument was out of the range
of valid values. Parameter name: Index was out of range. Must be
non-negative and less than the size of the collection
at
System.Collections.CollectionBase.System.Collections.IList.get_Item(Int32
index)
at System.Windows.Forms.CurrencyManager.EndCurrentEdit()
at System.Windows.Forms.CurrencyManager.ChangeRecordState(Int32
newPosition, Boolean validating, Boolean endCurrentEdit, Boolean
firePositionChange, Boolean pullData)
at System.Windows.Forms.CurrencyManager.set_Position(Int32 value)
at System.Windows.Forms.ListBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ListBox.WmReflectCommand(Message& m)
at System.Windows.Forms.ListBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

This is the source code I'm using (C#):

Collection.cs
public class Collection : System.Collections.CollectionBase
{
private Collection()
{
}
public static Collection NewCollection()
{
return new Collection();
}
public void Remove(CollectionItem item)
{
if (this.List.Contains(item))
this.List.Remove(item);
}
public int Add(string displayText, string valueText)
{
return this.List.Add(CollectionItem.NewCollectionItem(displayText,
valueText));
}
public CollectionItem this[int index]
{
get{return (CollectionItem)this.List[index];}
}
}

CollectionItem.cs
public class CollectionItem
{
private string _displayText = string.Empty;
private string _valueText = string.Empty;

public string DisplayText
{
get{return this._displayText;}
set{this._displayText = value;}
}
public string ValueText
{
get{return this._valueText;}
set{this._valueText = value;}
}
private CollectionItem(string displayText, string valueText)
{
this._displayText = displayText;
this._valueText = valueText;
}
public static CollectionItem NewCollectionItem(string displayText, string
valueText)
{
return new CollectionItem(displayText, valueText);
}
}

Form code:
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ListBox lisItems;
private Collection items = Collection.NewCollection();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

items.Add("One", "1");
items.Add("Two", "2");
items.Add("Three", "3");
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if (this.lisItems.SelectedItem == null)
return;

CollectionItem item = (CollectionItem)this.lisItems.SelectedItem;
this.lisItems.SuspendLayout();
this.lisItems.DataSource = null;

items.Remove(item);
this.lisItems.DataSource = items;
this.lisItems.DisplayMember = "DisplayText";
this.lisItems.ValueMember = "ValueText";

this.lisItems.ResumeLayout();
}
}

NOTE: I just paste the relevant code!


Upon clicking the Remove button, I'm removing the selected item from the
collection and re-binding the collection. I can remove any element, BUT ONLY
THE LAST ONE GIVES ME THE ERROR.



Thanks in advance for your help
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top