How to insert data from List into ListBox? - c#

I have created a List called employees and I want to input all of the information from that List into a list box on the form.
I cannot believe I have forgotten this I have had a look around and I cannot find any concise information, I have a study book, but they use a TextBox instead of a ListBox and they only work with arrays and simple data types.
List<Employee> employees = new List<Employee>();
This is the list, it contains employees
Employee employee1 = new Employee(1111, "Name", "Skill Set");
I have created an instance of List
Then I add it to the list box on the form
lstFree.Items.Add(employees);
Yet it only appears as 'collection'
What am I doing wrong?

The Add method expects a single instance of your class. When you pass a collection to it, it calls ToString() and you end up seeing the full class name of the collection. Not what you want.
Instead, you could use a loop:
foreach (var emp in employees)
lstFree.Items.Add(emp);
Or just assign it to DataSource:
listBox1.DataSource = employees;
You'll also want to tell it which property to display to the user (and optionally, which property to use as the underlying value):
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "EmpId"; // guessing what your class properties might be called

List<Employee> employees = new List<Employee>();
Employee employee1 = new Employee(1111, "Name", "Skill Set");
Employee employee2 = new Employee(2222, "Name", "Skill Set");
employees.Add(employee1);
employees.Add(employee2);
foreach(var empl in employees)
{
listBox1.Items.Add(empl.ToString());
}
In Employee class:
public override string ToString()
{
return ""; // return what you need
}

Consider using AddRange.
object[] arr = Enumerable.Range(1, 10000).Select(i=>(object)i).ToArray();
Compare time of this
// 1,29s
foreach (int i in arr)
{
listBox1.Items.Add(i);
}
to this
// 0,12s
listBox1.Items.AddRange(arr);

Related

Combining Data from class into a DataTable using Linq

I have a class like so
class Person(){
int Id;
string Name;
string SomePersonalInfo;
}
and a datatable with columns being Id, Name, and SomePersonalInfo. I also have a collection housing data in a List.
List<Person> = new Id = 1, Name = "So So"
List<Person> = new Id = 1, SomePersonalInfo= "Something"
I am trying to use linq so I dont have multiple for each statements to add Name and SomePersonalInfo in the datatable or making unnessary steps like keep getting the datarow. ANy suggestions
If you already have a strongly typed list, why do you want to have a loosely typed DataTable at all? Also, there is no good way to create a DataTable via LINQ-query without having DataRows.
Therefore i would simply use a loop which is readable and efficient:
foreach(Person p in persons)
tblPerson.Rows.Add(p.Id, p.Name, p.SomePersonalInfo);
Update acc. comment:
no I already have the datatable I am just trying to update the
datatable from the collection
Then you have to find the intersection first, use Enumerable.Join:
var inBoth = from p in persons
join row in tblPersons.AsEnumerable()
on p.Id equals row.Field<int>("Id")
select new { Person = p, Row = row };
foreach(var b in inBoth)
{
b.Row.SetField("Name", b.Person.Name);
b.Row.SetField("SomePersonalInfo", b.Person.SomePersonalInfo);
}

Why one needs to create a new objects on each iteration of a loop when populating a List?

I am working list of objects. My code looks something like this
public class emp
{
public string emp_name{get;set;}
public int emp_id{get;set;}
}
List<emp> emplist = new List<emp>;
emp empobj = new emp();
// fetching data from data table
foreach (DataRow row in ds.Tables[0].Rows)
{
// initialize emp object
empobj.emp_name = row["emp_name"].ToString();
empobj.emp_id = (int)row["emp_id"];
// add empobject to emp list
emplist.add(empobj);
}
If 2 records are fetched from table then my list shows last record details in each list object.
what i found was if i dont create new emp object every time and add to list it overrides the previous value in list also.
solution for this is
// fetching data from data table
foreach (DataRow row in ds.Tables[0].Rows)
{
// create new object every time
emp empobj = new emp();
// initialize emp object
empobj.emp_name = row["emp_name"].ToString();
empobj.emp_id = (int)row["emp_id"];
// add empobject to emp list
emplist.add(empobj);
}
Can any one please tell me why is it so?
If you don't create a new Emp object every time, you overwrite and insert the same object every time.
Imagine a piece of paper. You write on it, you put it into a book. Writing on the same piece of paper and putting in into the book multiple times will just not work. It will be a mess of writing on a single page. For every page you need a new piece of paper.
When you add to the emplist, you are adding 'empobj', which is a reference to a emp object.
Unless you create a new emp object each time, and assign that new entry to the empobj reference, you are just adding the same reference again and again.
Therefore, when you change the contents of that one reference, you change all the entries in the list.
In your code you are creating a single instance of the emp class, overwriting the elements in it for each row, and saving multiple references to the same object into the list.
You need to change the code to:
List<emp> emplist = new List<emp>;
// fetching data from data table
foreach (DataRow row in ds.Tables[0].Rows)
{
// initialize emp object
emp empobj = new emp();
empobj.emp_name = row["emp_name"].ToString();
empobj.emp_id = (int)row["emp_id"];
// add empobject to emp list
emplist.add(empobj);
}
In basic terms, your first piece of code effectively does this:
emp empobj = new emp();
empobj = new emp();
empobj = new emp(); // "final" version of the object
emplist.Add(empobj); // Same (final) added each time.
emplist.Add(empobj);
emplist.Add(empobj);
...
Your last piece of code effectively does
emplist.Add(new emp()); // New object each time.
emplist.Add(new emp());
emplist.Add(new emp());
...
2 Sidenotes:
You might want to simplify your code like this:
foreach (DataRow row in ds.Tables[0].Rows)
{
emplist.add(new empobj{
emp_name = row["emp_name"].ToString(),
empobj.emp_id = (int)row["emp_id"]
});
}
..and you might want to stick to naming conventions to make your code easier to read and understand; that is, use Emp for class name (capitalized). The same goes for properties, but there, avoid the underscores (this is to separate them from fields and other variables):
public string EmpName{ get; set; } and public int EmpId{ get; set; }.
When you do emp empobj = new emp();, you create a new instance of emp.
This line of code tells the memory allocator to assign memory to the new instance of emp object.
In your first example, you only had one instance, and you were over-writing the properties value in the foreach loop.
In the second example though, you were creating a new instance of emp object within the loop.
We could say that List stores references to objects, that's why in first case we add same reference, but in second case we add references to different objects, because empobj in each cycle is a new object.

Return a List that contain the same Object

I'm working with ASP.net Web Service C#.net3.5 and using the LINQ TO SQL to manipulate with SQL DataBase
and I want to return all the countries information from Countries Table,
so I wrote a web method that return a List of object, each object have two data field Country_Id, Country_Name and here is the method :
public List<CountryObject> ReturnAllCountries()
{
ProjectTwoDataBaseDataContext DataBase = new ProjectTwoDataBaseDataContext();
var Country = from a in DataBase.Countries
select new {a.Country_Id,a.Country_Name };
CountryObject TempObject = new CountryObject();
List<CountryObject> TempList = new List<CountryObject>();
foreach (var a in Country)
{
TempObject.setCountry_Id(a.Country_Id);
TempObject.setCountry_Name(a.Country_Name);
TempList.Add(TempObject);
}
return TempList;
}
but when I run the code I get a List that contains the same Object, and this object have the values that get from the last round of Foreach.
I try the Following :
public List<CountryObject> ReturnAllCountries()
{
ProjectTwoDataBaseDataContext DataBase = new ProjectTwoDataBaseDataContext();
var Country = from a in DataBase.Countries
select new {a.Country_Id,a.Country_Name };
CountryObject TempObject;
List<CountryObject> TempList = new List<CountryObject>();
foreach (var a in Country)
{
TempObject = new CountryObject();
TempObject.setCountry_Id(a.Country_Id);
TempObject.setCountry_Name(a.Country_Name);
TempList.Add(TempObject);
}
return TempList;
}
and I get what I want >> WHy ????
The two loops do very different things:
In the first example, you're only creating one object/ Then every time through the loop, modifying the same object, then re-adding it to the list. So your list contains a bunch of references to the same object, over and over again.
This happens because CountryObject, like all classes is a reference type. When you add the instance to TempList you are only adding a reference to that instance, not a copy of it, so when you later modify the instance, those changes will be reflected in the list because it only has a reference to the same instance.
In the second example, creating a new object on every iteration and adding that newly created object to the loop.
Because you're creating a new instance every time, the instances which the list references are not getting modified.
Further Reading
Value Types and Reference Types
Your first code snippet only creates one object that you put into the list multiple times. The second creates one per iteration of the foreach loop.
On another note I would suggest changing CountryObject to have Id and Name properties and you won't need to use an anonymous class in the Linq query. Properties are preferable over get and set methods.
public class CountryObject
{
public int Id { get; set; }
public string Name { get; set; }
}
public List<CountryObject> ReturnAllCountries()
{
ProjectTwoDataBaseDataContext DataBase = new ProjectTwoDataBaseDataContext();
var Country = from a in DataBase.Countries
select new CountryObject{Id=a.Country_Id, Name=a.Country_Name };
return Coutry.ToList();
}

How to fill the data into the datatable from variable list of data

I have a little task, I want assign data to my combobox as datasource, display member, value member from SQL Server table of a single column, by using Linq-to-SQL.
I get the required data from table like
var Uom = SpOpDcontx.Ptr_UOMs.Select(c => c.UM_Typ).Distinct().ToArray();
The data is being assigned to Uom variable, so I want to assign this data into my combobox datasource. Can any one help me please?
I don't understand why you mention a datatable when you don't use it and don't need it for this anyway. You simply need to do the following:
combo.DataSource = Uom;
combo.DisplayMember="UM_Typ";
combo.ValueMember="UM_Typ";
why don't you use List?
public class Test
{
// your all return properties goes here
public string Typ;
}
public class Test2
{
public List<Test> GetRequireData()
{
var Uom = SpOpDcontx.Ptr_UOMs.Select(c => new Test()
{
Typ = c.UM_Typ)
})
.Distinct();
return Uom.ToList<Test>();
}
}
Now, you can call GetRequireData() in your form as;
var obj = new Test2();
combo.DisplayMember="UM_Typ";
combo.ValueMember="UM_Typ";
combo.DataSource = obj.GetRequireData();

gridview with arraylist not showing data

I have a gridview that I populate with values I get from a powershell command. For example my powershell command is get-command. I know the command returns the values. Here is my code however my gridview never shows the data.
ArrayList boxesarray = new ArrayList();
foreach (PSObject ps in commandResults)
boxesarray.Add(ps.Properties["Name"].Value.ToString());
boxes.DataSource = boxesarray;
boxes.DataBind();
I know the value is there because I replaced the last two lines with a label and was able to see the value.
boxlabel.text = boxesarray[4];
I must be missing something. Help please.
The GridView requires a collection or IEnumerable of classes which have properties, and the properties are mapped to columns.
An array like yours have value typed objects (strings) which has no roperties, so you can't bind the properties to the columns.
ArrayList boxesarray = new ArrayList();
You could create a simple class like this:
public class PropertyContainer
{
public string Value {get;set;}
}
// NOTE: you can override ToString(); to customize String.Format behaviour
// and to show it in the debugger (althought there's other way for this, using
// DebuggerDisplayAttribute)
And create and populate an array of this class, which will be correctly bound to the datagrid.
foreach (PSObject ps in commandResults)
boxesarray.Add(
new PropertyContainer { Value = ps.Properties["Name"].Value.ToString()});
boxes.DataSource = boxesarray;
boxes.DataBind();
Other option is to convert your array to an array of objects using LINQ. You can even use anonymous object if the data grid columns are set to be automatically created.
// anonymous type
var dataForBinding = boxesArray.select(val => new {Value = val});
// array of the class
var dataForBinding = boxesArray.select(val => new PropertyContainer
{ Value = val });
You can bind this data to your gridview, and it will work perfectly.
You can try
.DataSource = (from ps in commandResults
select { Name:ps.Properties["Name"].Value.ToString() }).ToList();
Or
.DataSource = (from name in yourarraylist
select { Name:name.ToString() }).ToList();

Categories