Not getting an expected index from list - c#

I have a list box that displays a collection. Initially the list box only contains a default database of two objects. The user adds new objects to the collection and it is updated in the list box.
Prior to the user adding a new object, my code works as intended.
Code for loading objects into the list box.
private void FillStudentListBox()
{
lstStudents.Items.Clear();
for (int i = 0; i < students.Count; i++)
{
Student s = students[i];
lstStudents.Items.Add(s.GetDisplayText());
}
}
My update button code:
public void btnUpdate_Click(object sender, EventArgs e)
{
int target = Convert.ToInt16(lstStudents.SelectedIndex);
if (target != -1)
{
UpdateStudentScores updateStudentScores = new UpdateStudentScores(target);
updateStudentScores.Show();
}
}
If I click on one of the default users and then click Update, the form opens and is populated with the correct data. However if I add a new object and then click Update on the new object I get an error in this part of my code:
public Student this [int i]
{
get
{
return students[i];
}
set
{
students[i] = value;
Changed(this);
}
}
I'm sure the collection isn't getting updated correctly. Somewhere here:
private void button2_Click(object sender, EventArgs e)
{
if (IsValidData())
{
List<string> result = txtScores.Text.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries).ToList();
student = new Student(txtName.Text, result.Select(int.Parse).ToList());
this.Close();
}
}
The List Box is properly being filled but the index count is still 2 when it should be 3. What simple mistake did I make on the way?
Here's where student is supposed to be added to my collection:
private void btnAddNew_Click(object sender, EventArgs e)
{
AddNewStudent addStudentForm = new AddNewStudent();
Student student = addStudentForm.GetNewStudent();
if (student != null)
{
students += student;
}
}
I get the feeling that this code is deigned to already have the student object complete at the time of the button click.

Arrays are fixed length once they're declared. OutOfRangeException when trying to pull data from an array usually indicates that you are searching in an index that doesn't exist.
Instead of using an array, why not use a list? Then, you could use stuff like foreach.
But if you don't want to do that, you're going to have to find a way to update your array (redefine it to be bigger) so that it doesn't attempt to return data that's out of range. :)

Related

How to filter a specific record from BindingList c#

I have a bindinglist and after populating it, the list will be bind to a listbox.
private BindingList<VersionControlLabel> allTfsLabelList = new BindingList<VersionControlLabel>();
Versioncontrollabel class contains Name,version no, modified date etc..
Current implementation is when loading the form all the versions are load into the listbox then we have go through every item to find the specific one. Instead I want to add a textbox and when I type I want to show the record which has a exesiting word in textbox.
if user type the version number continuously the listbox should show the matching record
As enumrator properties are not available when I use the linq. How to do this?
I implemented something like this. But its not working. its not linq
private void txtSearchLabel_KeyUp(object sender, KeyEventArgs e)
{
if (!string.IsNullOrEmpty(txtSearchLabel.Text))
{
string text = txtSearchLabel.Text;
foreach (VersionControlLabel part in allTfsLabelList)
{
if(part.LabelId.ToString().Contains(text))
{
lstLabels.DataSource = part;
}
else
{
lstLabels.DataSource = allTfsLabelList;
}
}
}
}
If you want to just do ad hoc filtering then you can do something like this:
private List<string> allItems = new List<string>();
private void DisplayFilteredList()
{
var searchText = textBox1.Text.Trim();
listBox1.DataSource = searchText.Length == 0
? allItems
: allItems.Where(s => s.Contains(searchText)).ToList();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
DisplayFilteredList();
}

Add an empty row at the last in the DatagridView in Winform

I have one repository which contains a method which fetches the whole list from the database and the form load method as below. I have to add one empty row under the last row on a button click, so that I can edit the cells and save into database (I have another method for that).
Repository:
//display_tbl is storedproc
public List<ABC> FetchActiveABC() //Method for fetching the whole list into datagridview
{
var listABC = new List<ABC>();
try
{
using (var cmd = _db.GetStoredProcCommand("display_tbl"))
{
using (var a = new SafeDataReader(_db.ExecuteReader(cmd)))
{
while (a.Read())
{
listABC.Add(Loadabc(a));
}
}
}
}
catch { /* ... */}
return listABC;
}
Form:
private List<ABC> lstABC = null;
private void Form1_Load(object sender, EventArgs e)
{
lstABC = new ABCRepository().FetchActiveABC();
DataGridView.DataSource = lstABC;
}
This displays the whole list into datagridview.
Welcome Sarthak in stackoverflow.
As per you, you want to add one row at the last after the ABCRepository data loads.
So friend you can try this,
dataGridView1.Rows.Add(1);
This code will add one row and if you want to add the row at last so you can write this code after your code like this,
private void Form1_Load(object sender, EventArgs e)
{
lstABC = new ABCRepository().FetchActiveABC();
DataGridView.DataSource = lstABC;
dataGridView1.Rows.Add(1);
}

Add and delete text to/from ListBox hosted in WinForm using C#

I am working on a simple application that to add/delete string/s into an array and show that in ListBox.
My code shows only the latest value that was typed into the textBox and
private void Add_Click(object sender, EventArgs e)
{
string add = textBox1.Text;
List<string> ls = new List<string>();
ls.Add(add);
String[] terms = ls.ToArray();
List.Items.Clear();
foreach (var item in terms)
{
List.Items.Add(item);
}
}
private void Delete_Click(object sender, EventArgs e)
{
}
This code makes no sense. You are adding one single item to a list, then convert it to an array (still containg one item) and finally loop through this array, which of course adds one item to the previously cleared listbox. Therefore your listbox will always contain one single item. Why not simply add the item directly?
private void Add_Click(object sender, EventArgs e)
{
List.Items.Add(textBox1.Text);
}
private void Delete_Click(object sender, EventArgs e)
{
List.Items.Clear();
}
Also clear the listbox in Delete_Click instead of Add_Click.
If you prefer to keep the items in a separate collection, use a List<string>, and assign it to the DataSource property of the listbox.
Whenever you want the listbox to be updated, assign it null, then re-assign the list.
private List<string> ls = new List<string>();
private void Add_Click(object sender, EventArgs e)
{
string add = textBox1.Text;
// Avoid adding same item twice
if (!ls.Contains(add)) {
ls.Add(add);
RefreshListBox();
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Delete the selected items.
// Delete in reverse order, otherwise the indices of not yet deleted items will change
// and not reflect the indices returned by SelectedIndices collection anymore.
for (int i = List.SelectedIndices.Count - 1; i >= 0; i--) {
ls.RemoveAt(List.SelectedIndices[i]);
}
RefreshListBox();
}
private void RefreshListBox()
{
List.DataSource = null;
List.DataSource = ls;
}
The problem with code is quite simple. Instead of adding new item to list your code creates new list with one added item only. I am trying to interpret functions of program and they seem to be:
Enter new text into top level text box.
If Add button is clicked your item goes on top of the list (if it's bottom see end of my answer).
If item(s) is selected in list and Delete is clicked selected item(s) is/are deleted.
To achieve this you should first insert text on top of the list by using Add_Click code, than delete selected items using Delete_Click code. There is additional code to guard against inserting empty or white space only strings plus trimming of leading and trailing white space.
private void Add_Click(object sender, EventArgs e)
{
// Since you do not want to add empty or null
// strings check for it and skip adding if check fails
if (!String.IsNullEmptyOrWhiteSpace(textBox1.Text)
{
// Good habit is to remove trailing and leading
// white space what Trim() method does
List.Items.Insert(0, textBox1.Text.Trim());
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Get all selected items indices first
var selectedIndices = List.SelectedIndices;
// Remove every selected item using it's index
foreach(int i in selectedIndices)
List.Items.RemoveAt(i);
}
To complete adding and deleting logic I would add Delete All button which would just call List.Items.Clear(). If you prefer to add text at the end just use Add method form #Olivier Jacot-Descombes answer.
You can use in C#:
private void Delete_Click(object sender, EventArgs e)
{
if(myList.Contains(textbox1.value))//if your list containt the delete value
{
myList.Remove(textbox1.value); //delete this value
}
else
{
//the list not containt this value
}
}
and you can use the same method for validate if a value exist when try to add
private void AddItem()
{
if (!String.IsNullEmptyOrWhiteSpace(textBox1.Text))
{
var newItem = textBox1.Text.Trim();
if (!List.Items.Contains(newItem))
{
List.Items.Add(newItem);
// Alternative if you want the item at the top of the list instead of the bottom
//List.Items.Insert(0, newItem);
//Prepare to enter another item
textBox1.Text = String.Empty;
textBox1.Focus();
}
}
}
private void Add_Click(object sender, EventArgs e)
{
AddItem();
}
Private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
AddItem();
}
}
private void Delete_Click(object sender, EventArgs e)
{
// Remove every selected item using it's index
foreach(var item in List.SelectedItems)
{
List.Items.Remove(item);
}
}

ListBox causes program to crash when clicking in an empty area

I'm creating a flip card program that lets you insert a word and it's description. The word is added to a ListBox whilst the description is held in a string array. I've told the program to find the correct description once a ListBox item is clicked as shown in the code below. although this causes the program to crash if the user clicks on an empty area in the ListBox. How can I get around this?
public partial class Form1 : Form
{
int i = 0;
string[] details = new string[20];
private void insertbtn_Click(object sender, EventArgs e)
{
listBox1.Items.Add(inserttbx.Text); //Adds word to the ListBox
}
private void editDescbtn_Click(object sender, EventArgs e)
{
details[i] = descriptiontbx.Text; //adds text from descriptiontbx to "details" array
i++;
}
private void listBox1_Click(object sender, EventArgs e)
{
if(i == 0) //int i equals the amount of items in the ListBox.
{
}
else
{
int b = listBox1.SelectedIndex;
descriptiontbx.Text = details[b];
//"details" string array, will open the correct description
//depending on which ListBox item is selected.
}
}
}
Diagram of my program
Translations:
Infoga: Insert
Redigera: Edit
Note that all the functions in the program are not included in the code!
ListBox.SelectedIndex is:
A zero-based index of the currently selected item. A value of negative one (-1) is returned if no item is selected
Source
Therefore if no item is selected:
int b = listBox1.SelectedIndex;
descriptiontbx.Text = details[b];
will cause the crash as b is -1, which is out of range for an array. Add a check to make sure that SelectedIndex >= 0 before trying to use the value.

update a list after deleting an item

i have a form that when i add a item it stores it within a list and adds it to a checklistbox
i have a button that deletes the item from the checklist box, but how would i get it so that when i delete it from the checklistbox it also deletes it within the list its been stored in
here is the code for the delete button
private void btnDelete_Click(object sender, EventArgs e)
{
for (int i = clbSummary.CheckedIndices.Count - 1; i >= 0; --i)
{
clbSummary.Items.RemoveAt(clbSummary.CheckedIndices[i]);
}
}
Why don't you do remove the item from the list within the btnDelete_Click method.
For example:
private void btnDelete_Click(object sender, EventArgs e)
{
for (int i = clbSummary.CheckedIndices.Count - 1; i >= 0; --i)
{
object item = clbSummary.Items[clbSummary.CheckedIndices[i]];
myList = myList.Remove(item);
clbSummary.Items.RemoveAt(clbSummary.CheckedIndices[i]);
}
}
I'm not sure if you can use the [] operator on Items, but this is to give you a general idea.
Set the checklistbox DataSource property to the list where you are storing the items. When you make any changes to the list, your checklistbox will update.

Categories

Resources