Populating a combobox with List<string> - c#

After a combobox index changes, another combobox has to be populated with List<string> values. How am I able to do this?
For example:
Form (This is the way I'm having it now, incorrect though):
private void cbSelectEditFunction_SelectedIndexChanged(object sender, EventArgs e)
{
cbSelectEditName.Items.Add(emp.FindEmployeeinFunction(cbSelectEditFunction.Text));
}
Class method:
public List<string> FindEmployeeinFunction(string aFunction)
{
List<string> EmployeeListFunction = new List<string>();
foreach (Employee TempEmployee in EmployeeList)
{
if(TempEmployee.Function == aFunction)
{
EmployeeListFunction.Add(TempEmployee.Username);
}
}
return EmployeeListFunction;
}
Hope it's understandable this way. Let me know if I've forgotten something!

I think AddRange is the method you're looking for
//Assuming you don't want to continually add new items use Clear()
cbSelectEditName.Items.Clear();
//Use AddRange to add the list. ToArray() is used to convert List<> to string[]
cbSelectEditName.Items.AddRange(emp.FindEmployeeinFunction(cbSelectEditFunction.Text).ToArray());

Related

How to extract selected item from Listbox as an object

How to extract a selected item from Listbox as an object. Currently, I'm taking all records from DB and I add them to the Listbox in the following way:
var allEmployees = GetAll();
foreach (var emp in allEmployees)
{
var empFull = $"{emp.Id} - {emp.Name} {emp.Surname} - {emp.Email}";
listBoxViewEmp.Items.Add(empFull);
}
However, I find it challenging to make the listBoxViewEmp.SelectedItem to object since I'm taking the entire string that contains id, name, surname, and email.
private void btnUpdate_Click(object sender, EventArgs e)
{
if(listBoxViewEmp.SelectedItem != null)
{
var newForm = new UpdateForm(listBoxViewEmp.SelectedItem);
newForm.Show();
}
else
{
MessageBox.Show("Please select employee first");
}
}
What is the best way to handle this kind of issue?
Update:
Here is my attempt, but I got only objects now in the listbox
var allEmployees = GetAll();
foreach (var emp in allEmployees)
{
var empFull = (Employee)emp;
listBoxViewEmp.Items.Add(empFull);
}
enter image description here
The string that appears for any object added as an item to a ListBox control will be the return value of the ToString method of that object. In your case, you added a string directly to the list. So there's (likely) no way to recover the original object from the formatted string you created for that object.
Instead, override ToString for your Employee object (if appropriate to do so).
Alternatively, you can create a wrapper class whose job it is to remember the original object and to provide a custom ToString implementation for the remembered object. Such a generic formatter class might look like:
public class Formatter<T>
{
public Formatter(T obj, Func<T, string> fnFormat)
{
this.obj = obj;
this.fnFormat = fnFormat;
}
public T obj;
public Func<T, string> fnFormat;
public override string ToString() => fnFormat(obj);
}
Then, when you add items to the list box, add a Formatter wrapping that item instead. Its ToString method will be called, which will call the custom formatter for that item.
foreach (var employee in employees)
{
this.listBox1.Items.Add(new Formatter<Employee>(employee,
emp => $"{emp.Id} - {emp.Name} {emp.Surname} - {emp.Email}"));
}
And to access the original Employee, case the SelectedItem back to the Formatter<Employee> and access its remembered object field obj. Now you have the original Employee object back (or DB record or entity or whatever it was originally.) Example usage:
private void button1_Click(object sender, EventArgs e)
{
Employee employee = (this.listBox1.SelectedItem as Formatter<Employee>)?.obj;
this.label1.Text = employee?.Id.ToString();
}
You can use databinding for this. Make a new readonly property which will return computed string you want. Than ListBox has some properties you can use:
Datasource - source of data which will be displayed. You can set here just simple List<Employee>.
DisplayMember - you set the name of the property, which value you want to see in the ListBox.
ValueMember - you set the name of the property which value you want to get for selected item using ListBox's SelectedValue property.
So you can do it this way:
// You should set these two properties in form's designer.
listBoxViewEmp.DisplayMember = "Info"; // "Info" is that new readonly property.
listBoxViewEmp.ValueMember = "Id";
var allEmployees = GetAll().ToList();
listBoxViewEmp.DataSource = allEmployees;
That's it. Now:
You will see in the listbox what you want to see there.
listBox.SelectedItem returns whole your Eployee object.
listBox.SelectedValue returns the Id value of selected employee.
If you have access to the Employee class, do that :
Main code:
var allEmployees = GetAll();
foreach (var emp in allEmployees)
{
var empFull = (Employee)emp;
listBoxViewEmp.Items.Add(empFull);
}
In class code :
class Employee
{
...
public override string ToString()
{
return $"{this.Id} - {this.Name} {this.Surname} - {this.Email}";
}
}
Now you are able to get the items from the listbox as Employee and it will also replace "JustTest.Models.Employee" in the ToString above.

How to make a listbox of relative item by previews item clicked?

I have a list of cars.
public static List<Car> cars;
After I clicked an item from this static list, i want to make another list that contains relatives cars, that i can be interested in.
How can I make such a list?
As basic example
private void ListBox1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var selectedItem = (Car)ListBox1.SelectedItem;
if (!ListBox2.Items.Contains(selectedItem.Name))
{
ListBox2.Items.Add(selectedItem.Name);
}
}
OUPUT:
I hope it helps. Happy coding.

How to initialize an array of ObservableCollection?

Im designing an UWP movie app and i need several ObservableCollections to store different movie lists. I wanna use ObservableCollection[Index], but dont know how to initialize it.
I've tried the following code but failed:
public static ObservableCollection<Subject>[] FullMovieList = new ObservableCollection<Subject>[6];
How can i accomplish it? Thx~
You create array of ObservableCollection<Subject> correctly.
But you create array only, not collection in array itself.
You should create collections also;
for (int a = 0; a < FullMovieList.Length; a++)
{
FullMovieList[a] = new ObservableCollection<Subject>();
}
Building a new collection each time you want to add range of objects is not good rather i would follow below design.
Build a class inheriting from ObservableCollection , so that you can access Items property which is protected and then create a AddRange method which will add items into it
public class MyObObservableCollection<T> : ObservableCollection<T>
{
public void AddRange(IEnumerable<T> items)
{
foreach (var item in items)
{
this.Items.Add(item);
}
}
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}

C# unable to understand how static property works

I am a novice to C# language. I have created a user form and added a listview (chnaged it to public) on it. Now I have added a static classlike this
public static class listView
{
private static ListView.ListViewItemCollection litm;
public static ListView.ListViewItemCollection listItems
{
get
{
Form1 frm = new Form1();
return frm.listView1.Items;
}
set
{
litm = value;
}
}
}
Now added following code behind a button ,
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(listView.listItems.Count.ToString()); //Works
listView.listItems.Add("Fail"); //Fails
this.listView1.Items.Add("HH"); //Works
}
Here, I am able to use get the count of items. I think get works. But when I am trying to add a new item, it does nothing. No error but no entry is added.
I am interested to learn why that's happening. Any guidance is appreciated.
In your getter for property, you are creating a new instance of form 1 and add item to that.
It is not related to being static or non-static.
Look at this:
get
{
Form1 frm = new Form1();
return frm.listView1.Items;
}
So when you
listView.listItems.Add("Fail");
you are adding item to list view of form 1 that you can't see it.
Infact every time you access listView.listItems property, you are creating a newinstance of form 1 and adding an item to its listview1.
But in this line:
this.listView1.Items.Add("HH");
you are adding the item to the list view that you are seeing.
To learn about static:
static (C# Reference)

How do I update underlying list when calling BindingSource.RemoveCurrent

I have the following simple class;
public class MyObject
{
public int Id {get;set;}
public string Name {get;set;}
}
List<MyObject> oList = new List<MyObject>();
My list is populated with some items. I then populate my BindingSource with the list like;
MyBindingSource.DataSource = oList; //contains some items in a list
My BindingSource is linked to a DataGridView (which doesn't really matter in this example), but depending on the selected row in the DataGridView, I then have the following method for my datagrid view clicked button;
private void MyDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == btnRemove.Index)
{
MyBindingSource.RemoveCurrent();
}
}
The call
MyBindingSource.RemoveCurrent()
removes the items from the DataGridView, but how do I remove the item from the underlying list which is oList.
I thought that assigning MyBindingSource.DataSource = oList, means the list shown in MyBindingSource.DataSource is actually pointing to oList ?
List<T> isn't smart enough to know things have changed, so try using a BindingList<T> from System.ComponentModel instead:
BindingList<MyObject> oList = new BindingList<MyObject>();

Categories

Resources