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);
}
CodePudding user response:
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();
}
CodePudding user response:
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 simpleList<Employee>
.DisplayMember
- you set the name of the property, which value you want to see in theListBox
.ValueMember
- you set the name of the property which value you want to get for selected item using ListBox'sSelectedValue
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 yourEployee
object.listBox.SelectedValue
returns theId
value of selected employee.