Disposing of list and listbox items - c#

Hey I have a really annoying problem I have a list of doubles and a list box. A user can enter a value into a textbox and then click EnterValue.
List<double> listDouble = new List<double>();
private void EnterValue_Click(object sender, EventArgs e)
{
//convert input to double
listDouble.Add(Convert.ToDouble(textBox1.Text));
textBox1.Clear();
//clear existing items
listBox1.Items.Clear();
// clear any existing list items
for (int i = 0; i < listDouble.Count; i++)
{
listBox1.Items.Add(listDouble[i]);
}
}
I then have another button the user can click which will sum that list of doubles entered.
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
CalculateSumOfList.ServiceReference1.Service1SoapClient client = new CalculateSumOfList.ServiceReference1.Service1SoapClient();
CalculateSumOfList.ServiceReference1.ArrayOfDouble arrayOfDoubles = new CalculateSumOfList.ServiceReference1.ArrayOfDouble();
arrayOfDoubles.AddRange(listDouble);
string result = client.CalculateSum(arrayOfDoubles);
label1.Text = result;
//for (int i = 0; i < listDouble.Count; i++)
//{
// listDouble.Remove(i);
//}
}
The problem here is that when the user enters a value it is added to the list which is fine, when then user enters another number the list displays fine, and when the user calculates the sum of the list the value is correct. But after that if the user then goes back to add more numbers to the list the "old" list is appended onto the end?
Ive tryed every means to dispose of that "old" list after the calculation has been done. But nothing works. Which ofcourse then ruins the second attempt.

Use listDouble.Clear() to completely clear the list.
Your loop (commented out in your code example) isn't working correctly. Just think it through:
First you remove the first element which makes the second element the new first element.
Now you remove the new second element (previously that was the third element). The original second element never gets removed.
This continues until half of the elements are removed ...

Related

TextBox.TextChange to update an onscreen ListBox in C#

Now this might not sound horribly cryptic, but I'm a little new to handling on-screen elements and Forms and such in C# so bear with me here. It's also going to be a bit of a long one, as I feel I should provide as much information as possible.
I have a TextBox object, which is added to my fSelect (which is my Form in this case), and it's done like this:
TextBox searchBox = new TextBox();
fSelect.Controls.Add(searchBox);
searchBox.Location = new Point(40, 255);
searchBox.Width = 520;
searchBox.TextChanged += new EventHandler(searchBox_TextChanged);
Now, as you can see every time something changes in the TextBox a certain operation is carried out. That operation would be:
private void searchBox_TextChanged(object sender, EventArgs e)
{
TextBox s = (TextBox)sender;
bool b = false;
List<string> f = new List<string>();
ListBox updatedLb = new ListBox();
updatedLb.Size = new System.Drawing.Size(568, 255);
updatedLb.SelectionMode = SelectionMode.MultiSimple;
foreach (string value in lb.Items)
{
if (value.IndexOf(s.Text, StringComparison.OrdinalIgnoreCase) >= 0)
{
f.Add(value);
b = true;
}
}
for (int i = 0; i < f.Count; i++)
{
updatedLb.Items.Add(f[i]);
}
s.FindForm().Controls.Remove(lb);
s.FindForm().Controls.Add(updatedLb);
}
Looking at that code, there's one element that needs explanation, lb. lb is in this case a public ListBox which contains a set amount of string elements. It is defined as a ListBox outside any method.
Now, in the method my searchBox was defined I filled my lb as follows:
foreach (string value in list)
{
lb.Items.Add(value.title);
}
(If it matters, I should also mention that the adding of strings to lb happens before it is inserted into the fSelect Form later.)
Now, for those who haven't guessed my question yet; I wish to present a user with a Form that has a ListBox on it. The elements in this ListBox will be whatever elements contain the string the user types into searchBox, AS the user types it.
The problem is, that the search is only carried out once, and the only thing that is searched for is the first key the user puts in the searchBox. IE: If I was the user and I was going to search for "key", and the first letter was "k", the list would update to show anything with "k" in the title. But when I tried to type the "e" it would not update or change. It would also not go revert back to the old list if the user removes part of the text in searchBox.
How do I go about getting a Form that shows me a ListBox with elements based on what a user entered into searchBox?
The problem is that you are looping though lb, which you delete the first time the text_Changed-Event triggers. So you don't have any items more that you can loop through and filter your ListBox. The easiest way to fix that would be not getting the items you loop though from the ListBox itself, but from a List<string> that you use to supply the ListBox.
Edit
Here's the way I'd do it:
In your form class you add a List<string>, this list is the base for your ListBox.
List<string> listBoxItems = new List<string>();
Now you can fill this list in your constructor with the items you want. Here are some ways to do it. For my example I'll just add all the items manually for simplicity.
listBoxItems.Add("Item1");
listBoxItems.Add("abc");
listBoxItems.Add("CDE");
listBoxItems.Add("Abra");
Then you want to fill your ListBox with the items from your List.
foreach (var s in listBoxItems)
{
listBox1.Items.Add(s);
}
Now you just need to handle the Text_Changed-Event. Instead of creating a new ListBox every time, you just edit the one we already have in the form and instead of looping though the items in the ListBox, which are already filtered, you loop though all the item saved in your List<string>.
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox s = (TextBox)sender;
listBox1.Items.Clear();
foreach (string value in listBoxItems)
{
if (value.IndexOf(s.Text, StringComparison.OrdinalIgnoreCase) >= 0)
{
listBox1.Items.Add(value);
}
}
}
In your code, you created a new ´ListBox´ each time you go into the loop, but you still try to use the items from your old one.
I hope this helps,
Dominik

C# 2 Comboboxes with identical, not twice-selectable content

I have a dialog form where the user has to selected which colums from a textfile he wants to use for drawing a graph.
If someone doesn't quite understand what I mean, please look at the following example:
The dialog opens
The user selects e.g. that the x-values of his graph shall be from the second column of the textfile
The user selects e.g. that the y-values of his graph shall be from the third column of the textfile
The user clicks "OK"
The problem I have is the following:
I want to prevent the user from selecting the same column for x and y values, which would result in a line in an angle of probably 45 degrees and make the graph useless.
Both comboboxes are filled with the same array of strings, which contains the headlines of the columns in the textfile. Getting those strings into the comboboxes works great, but:
I tried removing the item selected in one combobox from the other combobox and otherwise.
Before that, the currently selected item is stored in a variable and the items are reset to the default state, which means all headlines from the textfile.
But, as I programmatically set the index to where it was before, so that the user doesn't have to, the SelectedIndexChanged event fires and traps my code in an infinite loop.
public void setComboboxText()
{
cbX.Items.Clear();
cbY.Items.Clear();
cbX.Items.AddRange(cbText);
cbY.Items.AddRange(cbText);
}
void CbXSelectedIndexChanged(object sender, EventArgs e)
{
var item = cbX.SelectedItem;
setComboboxText();
cbX.SelectedItem = item;
cbY.Items.Remove(cbX.SelectedItem);
}
void CbYSelectedIndexChanged(object sender, EventArgs e)
{
var item = cbY.SelectedItem;
setComboboxText();
cbY.SelectedItem = item;
cbX.Items.Remove(cbY.SelectedItem);
}
The code does the following:
The currently selected item is temporarily stored
The items of the combobox are reset
The currently selected item is set to be the item stores before
The item selected in the changed box disappears from the other combobox
Any help appreciated, especially if someone could tell me if I can do what I want with another event or even without events.
Thanks in advance
I think this is what you are trying to achieve.
public partial class Form1 : Form
{
List<string> source1 = new List<string>();
List<string> source2 = new List<string>();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 10; i++)
{
source1.Add("item" + i);
source2.Add("item" + i);
}
comboBox1.Items.AddRange(source1.ToArray());
comboBox2.Items.AddRange(source2.ToArray());
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox2.Items.Contains(comboBox1.SelectedItem))
{
comboBox2.Items.Clear();
List<string> updatedList = new List<string>();
updatedList = (from x in source2
where !x.Equals(comboBox1.SelectedItem)
select x).ToList<string>();
comboBox2.Items.AddRange(updatedList.ToArray());
}
}
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Items.Contains(comboBox2.SelectedItem))
{
comboBox1.Items.Clear();
List<string> updatedList = new List<string>();
updatedList = (from x in source1
where !x.Equals(comboBox2.SelectedItem)
select x).ToList<string>();
comboBox1.Items.AddRange(updatedList.ToArray());
}
}
}
Make the source collections available avaiable to each combobox SelectedIndexChanged handlers
On each selection change update the source of the other combobox only if the newly selected item exists in the other combobox Items.

Textboxes in an Array, Connect 4

I'm trying to create a Connect 4 game using textboxes and buttons.
If you click on the button, the textbox background color is filled in and the text will either be filled with x or y.
private void button2_Click(object sender, EventArgs e)
{
Output_textBox.AppendText("You have inserted in Column 2");
Output_textBox.AppendText(Environment.NewLine);
TextBox[] boxes = { textBox21, textBox22, textBox23, textBox24, textBox25, textBox26 };
for (int i = 0; i < 6; i++)
{
if (boxes[i].BackColor != SystemColors.HotTrack)
{
boxes[i].BackColor = SystemColors.HotTrack;
boxes[i].Text = "Y";
}
}
}
(edited on 11/6/2013 2:25pm)
The Code above doesn't seem to work even though it seems to make perfect sense to me that it should.
What i want is for the textbox to turn one by one. So if i click on the button once. textbox11 changes first. Then if textbox11 is filled, textbox12 is filled next when i click on the button again etc.
The coloring needs to be from bottom to top in a column
About me: I'm new to coding. Sorry for the trouble
Thank you in advanced

Adding items to List<> of object which already contain data, add duplicate item in the List

I am developing a Windows phone app for which I want to get a list of first 15 object from my web service plus an extra item to represent the "Load next 15 items button" and bind it to a listbox. On selection of the last element or index(buttton), I want to remove the last item(button) from the list and call the service again to get the next 15 items plus the button item which will again add up to the current list without clearing the list. And the same process goes on as we select the last item from the listbox.
My problem is I am able to get it correctly for the first round. In the second round, the next 15 element is added to the list twice. I don't know what is the real problem. I am not getting any error or exception also.
Below is what I have done so far :
private void ListBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int LastIndex=app.imgItem.Count - 1;
if (ListBox1.SelectedIndex == LastIndex)
{
app.imgItem.Remove(app.imgItem[app.imgItem.Count-1]);
proxy.SelectNextItemsCompleted += new EventHandler<ServiceReference1.SelectNextItemsCompletedEventArgs>(proxy_SelectNextItemsCompleted);
int id = app.imgItem.Last().Id;
proxy.SelectNextItemsAsync(categoryID, id);
}
}
void proxy_SelectNextItemsCompleted(object sender, ServiceReference1.SelectNextItemsCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("Cannot load data.");
return;
}
else
{
foreach (var item in e.Result)
{
ImgData idata = new ImgData();
idata.CategoryID = item.CategoryID;
idata.ImageID = item.ImageID;
idata.ImageTitle = item.ImageTitle;
idata.Thumbnail = item.Thumbnail;
app.imgItem.Add(idata);
}
}
ImageData btnData = new ImageData();
btnData.CategoryID = 0;
btnData.ImageID = 0;
btnData.ImageTitle = "";
btnData.Thumbnail = "Images/loadButton.jpg";
app.imgItem.Add(btnData);
ListBox1.ItemsSource = app.imgItem;
}
It looks like you're re-registering an event handler in the SelectionChanged event handler, and as a result, the SelectNextItemsCompleted handler is probably getting called twice the second time around:
proxy.SelectNextItemsCompleted += new EventHandler<ServiceReference1.SelectNextItemsCompletedEventArgs>(proxy_SelectNextItemsCompleted);
You should probably be registering that event handler somewhere else where the code only runs once.

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?

Categories