How to populate asp:GridView from code? - asp.net

I have a List<string[]> items list filled with arrays of strings in my code. On the ASPX page, I have added a new grid view control:
<asp:GridView ID="ProductList" runat="server" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="ProductID" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product" SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True" SortExpression="SupplierName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:C}" HeaderText="Price" HtmlEncode="False" SortExpression="UnitPrice" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" />
</Columns>
</asp:GridView>
I know that I should specify the DataSourceID attribute for the grid view in a fashion similar to this:
<asp:GridView ... `DataSourceID="ObjectDataSource1" ... >
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
But, I don't know what do OldValuesParameterFormatString, SelectMethod and TypeName attributes represent. Also, I don't have the database to bind to, I just have the list of string arrays named items. Can you help me populate the grid view? It is not necessary to do it through the binding at all. Thanks!

You don't even need an ObjectDataSource. At Page_Load in the codebehind, you can parse through the string array list and create a DataTable on the fly.
Make sure to wrap this around a Not Page.IsPostback so that it doesn't rebind on postback.
List<string[]> stringList = null;
DataTable dt = new DataTable();
DataRow dr = null;
dt.Columns.Add("ProductName", System.Type.GetType("System.String"));
dt.Columns.Add("CategoryName", System.Type.GetType("System.String"));
dt.Columns.Add("SupplierName", System.Type.GetType("System.String"));
dt.Columns.Add("UnitPrice", System.Type.GetType("System.Double"));
dt.Columns.Add("Discontinued", System.Type.GetType("System.String"));
foreach (string[] s in stringList) {
foreach (string str in s) {
dr = dt.NewRow();
dr["ProductName"] = s[0];
dr["CategoryName"] = s[1];
dr["SupplierName"] = s[2];
dr["UnitPrice"] = s[3];
dr["Discontinued"] = s[4];
dt.Rows.Add(dr);
}
}
dt.AcceptChanges();
ProductList.DataSource = dt;
ProductList.DataBind();

Edit: You'll have to change some of this code to match your needs. I'm making assumptions on the data types stored in your string[] based on the GridView code you provided.
You'll want to look into creating a class to use for your items, instead of a string[]. Maybe something like:
public class MyObject
{
public string ProductName { get; set; }
public string CategoryName { get; set; }
public string SupplierName { get; set; }
public decimal UnitPrice { get; set; }
public bool Discontinued { get; set; }
}
You'd then need something to translate the string[] into MyObject:
private MyObject ConvertToMyObject(string[] values)
{
var myObject = new MyObject();
myObject.ProductName = values[0];
myObject.CategoryName = values[1];
myObject.SupplierName = values[2];
decimal unitPrice;
if (decimal.TryParse(values[3], out unitPrice))
{
myObject.UnitPrice = unitPrice;
}
bool discontinued;
if (boo.TryParse(values[4], out discontinued))
{
myObject.Discontinued = values[4];
}
}
Then you could use that method in your code and then bind:
protected void Page_Load(parameters here)
{
if (IsPostback)
{
var myObjects = new List<MyObject>();
foreach (string[] values in items)
{
myObjects.Add(ConvertToMyObject(values));
}
ProductList.DataSource = myObjects;
ProductList.DataBind();
}
}
Like I said in the comment, make sure you have access to items in the Page_Load event handler. Also, I typed this from memory, forgot the parameters in Page_Load. You most likely already have a Page_Load handler in your code behind though.

You can try this
List<string[]> items = List<string[]>();
//add items to List
GridView1.DataSource = items;
GridView1.DataBind();
Your GridView
<asp:GridView runat="server" ID="GridView1">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="stringLabel" Text="<%# Container.DataItem %>" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

Related

ASP.NET Error when binding a GridView to a List of Objects?

Error Message:
The data source for GridView with id 'FormProprietari' did not have
any properties or attributes from which to generate columns. Ensure
that your data source has content.
I have a ASP.NEt application in which I try to bind a GridView to a List<T> objects which from what I can tell on the net it should be possible.
This is my GridView:
<asp:GridView ID="FormProprietari" runat="server">
<Columns>
<asp:TemplateField >
<ItemTemplate>
<%#((Lab_TAP_web.Proprietar)Container.DataItem).NumeProprietar%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField >
<ItemTemplate>
<%#((Lab_TAP_web.Proprietar)Container.DataItem).PrenumeProprietar%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField >
<ItemTemplate>
<%#((Lab_TAP_web.Proprietar)Container.DataItem).ProprietarID%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And this is the function in which I add a new object of the Proprietar class I defined to the database then rebind the gridview to show it, I should mention that intially the database is empty and so is the gridview i,e it doesn't show up.
protected void Button2_Click(object sender, EventArgs e)
{
var Nume = TBNumeProprietar.Text;
var Prenume = TBPreNumeProprietar.Text;
MyCars db = DBSilo.db;
Proprietar newOwner = new Proprietar();
newOwner.NumeProprietar = Nume;
newOwner.PrenumeProprietar = Prenume;
newOwner.ProprietarID = (db.Proprietari.Count() + 1);
//newOwner.ProprietarID = 1;
db.Proprietari.InsertOnSubmit(newOwner);
db.SubmitChanges();
try
{
FormProprietari.DataSource = db.Proprietari.ToList();
}
catch (Exception)
{
throw;
}
FormProprietari.DataBind();
}
The problem being that I checked the List<Proprietar> which is the data source with breakpoints and the list always contains a Proprietar object.
Does anyone have a idea what I did wrong?
Moved from comment to Answer.
Please make sure you have getter and setter for each property of Proprietar class like this -
public class Proprietar
{
public string NumeProprietar { get; set; }
public string PrenumeProprietar { get; set; }
public int ProprietarID { get; set; }
}

Bind Collections To Gridview

protected void BindGV()
{
List<List<string>> list = new List<List<string>>()
{
new List<string>() {"Hussain","IT","Hyderabad" },
new List<string>() { "Sharief","IT","Bangalore"},
new List<string>() { "Shaik","IT","Chennai"}
};
gv1.DataSource = list;
gv1.DataBind();
}
I want to display only Name and City in Gridview. I want to use like:
<asp:Boundfield Datafield="" Headertext="Name"/>
How to use DataField in this case??
First of all, you should create a List with some class, rather than string. Then you can use class properties in you DataGrid as columns.
For example:
public class Personnel
{
public string Name { get; set; }
public string Department { get; set; }
public string Location { get; set; }
}
Then you can create a data source like:
protected void BindGV()
{
List< Personnel > list = new List< Personal >()
{
new Personnel {Name = "Hussain", Department = "IT", Location = "Hyderabad" },
new Personnel {Name = "Sharief", Department = "IT", Location = "Bangalore"},
new Personnel {Name = "Shaik", Department = "IT", Location = "Chennai"}
};
gv1.DataSource = list;
gv1.DataBind();
}
In your code behind create DataGrid like
<asp:DataGrid runat="server" ID="gv1" AutoGenerateColumns="False>
<Columns>
<asp:BoundColumn HeaderText="Name" DataField="Name" />
<asp:BoundColumn HeaderText="Dept" DataField="Department" />
<asp:BoundColumn HeaderText="City" DataField="Location" />
</Columns>
</asp:DataGrid>
And that should be it.
UPDATE: According to you comment, you want to access DataField programatically. You can do this by enumerating gv1.Columns property and then cast the result to BoundColumn. This will give you access to DataField and other properties.
as Husein said, first create class with Get , Set .
like
Public class BindGV
{
public string name { get; set ;}
public string Profile { get; set ;}
public string loc { get; set ;}
}
In aspx page Gridview BoundField....
<ItemTemplate..>
<b><%# DataBinder.Eval(Container, "DataItem.Title") %> </b>
<br />
<%# DataBinder.Eval(Container, "DataItem.Description") %>
</ItemTemplate>
... Or Apsx.cs code
BindGV.datasource=object.GetDetails();
BindGV.dataBind();
You can take benefit of linq
List<List<string>> list = new List<List<string>>()
{
new List<string>() {"Hussain", "IT", "Hyderabad"},
new List<string>() {"Sharief", "IT", "Bangalore"},
new List<string>() {"Shaik", "IT", "Chennai"}
};
linq query
var v = from li in list select new {Name = li[0], City=li[2]};
gv1.DataSource = v;
gv1.DataBind();
And gridview
<asp:DataGrid runat="server" ID="gv1" AutoGenerateColumns="False>
<Columns>
<asp:BoundColumn HeaderText="Name" DataField="Name" />
<asp:BoundColumn HeaderText="City" DataField="City" />
</Columns>
</asp:DataGrid>
But this is not a good Idea to use.
You should have a proper structure of you property as suggested by the two gentle men.

ASP.NET Binding DataSource to entire page with a single record

We currently use asp:Repeater with <%#Eval("SomeField")%> in aspx page to display data.
We would like to use a single record and bind it to a asp.net control on the aspx page so we can <%#Eval("SomeField")%>.
I have tried FormView, DetailsView, and other asp.net controls. All of which required a .ToList() or IEnumerable. However, we are returning ctx.Jobs.SingleOrDefault(j => j.ID == id);
We don't want to use asp:Label or asp:Literal ..
What can we do to use the <%#Eval("SomeField")%> in the page when returning a single record?
PRESENTER
public static Job GetByID(int id)
{
using (var ctx= new CareersEntities())
{
return ctx.Jobs.SingleOrDefault(j => j.ID == id);
}
}
CODE-BEHIND
protected void Page_Load(object sender, EventArgs e)
{
Job d = new Job();
d = JobPresenter.GetByID(ID);
fvJob.DataSource = d;
fvJob.DataBind();
}
ASPX PAGE
<asp:FormView ID="fvJob" runat="server">
<ItemTemplate>
<%#Eval("Title")%>
</ItemTemplate>
</asp:FormView>
Both DetailsView and FormView will work with a single object if it's using a data source control (such as ObjectDataSource). With ObjectDataSource you can return a single element from your Select method and the data source will then wrap it in a list just for the sake of the programming interface - but it's not something you'd ever see.
If you want to directly set the control's DataSource property and call DataBind, just wrap the object in an array and then pass that in.
Here's the DetailsView:
<asp:DetailsView runat="server" ID="DetailsView1" AutoGenerateRows="false">
<Fields>
<asp:TemplateField HeaderText="First name:">
<ItemTemplate><%# Eval("FirstName") %></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last name:">
<ItemTemplate><%# Eval("LastName") %></ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
And here's the DetailsView binding code in Page_Load:
var person = new Person { FirstName = "John", LastName = "Doe" };
DetailsView1.DataSource = new object[] { person };
DetailsView1.DataBind();
Or here's a FormView:
<asp:FormView runat="server" ID="FormView1">
<ItemTemplate>
First name: <%# Eval("FirstName") %><br />
Last name: <%# Eval("LastName") %><br />
</ItemTemplate>
</asp:FormView>
And here's the Page_Load code:
var person = new Person { FirstName = "John", LastName = "Doe" };
FormView1.DataSource = new object[] { person };
FormView1.DataBind();
And here's the model type (same in both DetailsView and FormView):
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
A DetailsView requires a List?! Anyhow, why don't you use ctx.Jobs.SingleOrDefault(j => j.ID == id).ToList() ?

How to Combine TemplateFields in ASP.Net GridView?

Everyone.
I have a question when combining cells in GridView. I konw how to combine BoundField cells, but I do not know how to combine TemplateField cells in asp.net GridView.
EDIT:
Perhaps I did not make my question clearly and I am sorry about that. My question is that I use GridView to bind data from db and There is a field named UserName, one user has several records in the db, so I want to combine UserName in one cell(i can combine it correctly). In the same way, I want to do some operation to this user such as Add, Delete. So i put these operations into TemplateField, but i do not konw how to combine TemplateField like BoundField. I have a low reputation, so i can not post images
Any good ideas?
Sorry for my poor english! Thanks in advance.
There isn't a way to merge/combine fields. I think you misunderstood the BoundFields/TemplateField. However you can use Eval() and Bind() to show/bind one or more expression into single cell//column..
Read MSDN articles:
BoundField
TemplateField
EDIT:
#loren : There is a field named UserName, one user has several records
in the db.
I guess you need to use "nested" grid or you may also use any data control (formview, detail view or ListView).
Here is demo that shows how to bind nested data controls.
I've define two classes - Contact, Info
public class Contact
{
public string Address{get;set;}
public string Phone {get;set;}
}
public class Info
{
public string UserName {get;set;}
private List<Contact> _addr=new List<Contact>();
public List<Contact> Address
{
get { return _addr; }
set { _addr = value; }
}
}
In .aspx page (Markup),
<asp:GridView
ID="GridView1"
runat="server"
AutoGenerateColumns="false"
onrowdatabound="GridView1_RowDataBound"
>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<p>
Username :
<asp:Literal
ID="UserName"
runat="server"
Text='<%#Eval("UserName") %>'
>
</asp:Literal>
</p>
<asp:GridView
ID="GridView2"
runat="server"
AutoGenerateColumns="false"
>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<p>Phone :
<asp:TextBox
runat="server"
ID="txtDetail"
Text='<%#Bind("Phone") %>'
></asp:TextBox>
</p>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and in code-behind (aspx.cs),
List<Info> info;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
info = new List<Info>()
{
new Info()
{
UserName="User1",
Address =
{
new Contact() { Phone="2929927", Address="Address1"},
new Contact() { Phone="2929928", Address="Address2"},
}
},
new Info()
{
UserName="User2",
Address =
{
new Contact() { Phone="2929929", Address="Address3"},
new Contact() { Phone="2929930", Address="Address4"},
}
},
};
GridView1.DataSource = info;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
Literal username=(Literal)e.Row.FindControl("UserName");
GridView view=(GridView)e.Row.FindControl("GridView2");
if (view != null)
{
var result = from ele in info
from add in ele.Address
where ele.UserName == username.Text
select add;
view.DataSource = result;
view.DataBind();
}
}
If possible, you can update the source type.
For example, if you an object data source and a model like this :
[DataObject]
public class MyOds{
[DataObjectMethod(DataObjectMethodType.Select)]
public ICollection<MyModel> GetMyModels()
{
var result = new ListMyModel();
Populate(result); // load model with any method of you choice
return result;
}
}
public class MyModel{
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string FullAddress {
get
{
return string.Format("{0} - {1} - {2}", Address, City, Country);
}
}
}
Note the FullAddress property. The idea is to build, for the view, properties easy to exploit. The ASPX can looks like this :
<asp:TemplateField HeaderText="Header">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text="Label">
<%# Eval("FullAddress")%>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
you can use Eval as bellow
<asp:TemplateField HeaderText="Header">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1" Text='<%#Bind("Phone") %>'></asp:TextBox>
<asp:TextBox runat="server" ID="txt2" Text='<%#Bind("Address") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>

What is an easy way to bind a gridview with dynamic columns?

I have a variable defined as follows:
Dim iRows As List(Of String())
I've also been converting that to a list of lists just to make it easier to work with.
Dim iRows As List(Of IList(Of String))
I would like to bind that list to a GridView using the contents of the nested array/list to dynamically define the columns. I don't know ahead of time how many columns there will be, but I do know that they are all the same throughout the list.
I'm just not real sure how to go about it. Thoughts?
Seems to me, that without knowing how your datasource looks like / how many columns there will be, there is no way to put each column into a different gridview column.
That means, fixed markup is not possible => You need to set the AutoGenerateColumns property to true.
You can set the HeaderText of each column by accessing the HeaderCollecion of the GridView, if you want to use a different
Another solution you might be interested in, would be not to use the GridView at all, if you are only interested in displaying data (meaning no edit or delete buttons) You could render your data into a html table with columns and rows, by using Reflection, like aleafonso suggested.
I have done something like this with c# which could possibly help you.
I will have a list of destinations which will be populated to a GridView.
The destination object must be serializable and cannot have nullable values. This is my example:
[Serializable]
public class destination
{
private int idDestination;
public int IDDestination { get; set; }
private string name;
public string Name { get; set; }
private string type;
public string Type { get; set; }
private string ringingTime;
public string RingingTime { get; set; }
private int priority;
public int Priority { get; set; }
private int huntBusy;
public int HuntBusy { get; set; }
public destination() { }
}
Every time you want to populate the GridView you will need to do the following:
GridViewDestination.DataSource = ConvertArrayListToDataTable(listSelectedDestinations);
GridViewDestination.DataBind();
where ConvertArrayListToDataTable is the following:
public static DataTable ConvertArrayListToDataTable(ArrayList arrayList)
{
DataTable dt = new DataTable();
if (arrayList.Count != 0)
{
dt = ConvertObjectToDataTableSchema(arrayList[0]);
FillData(arrayList, dt);
}
return dt;
}
public static DataTable ConvertObjectToDataTableSchema(Object o)
{
DataTable dt = new DataTable();
PropertyInfo[] properties = o.GetType().GetProperties();
if (o.GetType() == typeof(destination))
{
foreach (PropertyInfo property in properties)
{
DataColumn dc = new DataColumn(property.Name);
dc.DataType = property.PropertyType; dt.Columns.Add(dc);
}
}
return dt;
}
private static void FillData(ArrayList arrayList, DataTable dt)
{
foreach (Object o in arrayList)
{
DataRow dr = dt.NewRow();
PropertyInfo[] properties = o.GetType().GetProperties();
if (o.GetType() == typeof(destination))
{
foreach (PropertyInfo property in properties)
{
dr[property.Name] = property.GetValue(o, null);
}
}
dt.Rows.Add(dr);
}
}
As far as I know, this is using reflection: using the arraylist of destinations to bind it to a gridview.
On the other hand, your GridView should be defined like this:
<asp:GridView ID="GridViewDestination" runat="server" Visible="False" Width="98%" CssClass="GridView" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:Label ID="idNonAnsweredCreating" runat="server" Text='<%# bind("idDestination") %>' Visible="false"></asp:Label>
<asp:Label Visible="true" runat="server" ID="destinationLabelCreating" Text='<%# bind("name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<asp:Label Visible="true" runat="server" ID="destinationTypeLabelCreating" Text='<%# bind("type") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
As you can see, you will bind as many destinations properties as needed in each column of the GridView.
Hope this helps.

Resources