binding datatable to grid view - asp.net

I have the following code:
Imports System.Data
Partial Class Students_AddWishes Inherits System.Web.UI.Page
Public dt As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
dt.Columns.Add("ID", System.Type.GetType("System.Int32"))
dt.Columns.Add("univirsity", System.Type.GetType("System.Int32"))
dt.Columns.Add("major", System.Type.GetType("System.Int32"))
End Sub
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAdd.Click
Dim row1 As DataRow = dt.NewRow()
row1("ID") = dt.Rows.Count + 1
row1("univirsity") = ddlUnivs.SelectedValue
row1("major") = ddlMajors.SelectedValue
dt.Rows.Add(row1)
GridView1.DataSource = dt
GridView1.DataBind()
End Sub
End Class
The problem is it shows only one row or record. How to make it shows many records?

Your page load event you are not checking if it is a post back:
If Not IsPostBack Then
'process code if it is not a post back
End If
Everytime you click the btnAdd button your page does a post back to the server.
I just noticed that you probably are not understanding the life time of an object.
You had done this in your code:
Public dt As New DataTable
The problem with that is you have defined this is a class variable and once the page has loaded you have an instance of type dt that may have some columns associated with it. But as soon as you record an event such as a button click that reference is destroyed and a new dt is created.
You will have to make some use of session variables or a database to store the state of dt.
Here is an example in C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID", System.Type.GetType("System.Int32"));
dt.Columns.Add("univirsity", System.Type.GetType("System.Int32"));
dt.Columns.Add("major", System.Type.GetType("System.Int32"));
Session["MyDataTable"] = dt;
}
}
protected void btnAdd_Click(object sender, EventArgs e)
{
DataTable t = (DataTable)Session["MyDataTable"];
DataRow row1 = t.NewRow();
row1["ID"] = t.Rows.Count + 1;
row1["univirsity"] = 3;
row1["major"] = 31;
t.Rows.Add(row1);
Session["MyDataTable"] = t;
GridView1.DataSource = t;
GridView1.DataBind();
}
And the same code in vb.net:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If Not Page.IsPostBack Then
Dim dt As New DataTable()
dt.Columns.Add("ID", System.Type.[GetType]("System.Int32"))
dt.Columns.Add("univirsity", System.Type.[GetType]("System.Int32"))
dt.Columns.Add("major", System.Type.[GetType]("System.Int32"))
Session("MyDataTable") = dt
End If
End Sub
Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim t As DataTable = DirectCast(Session("MyDataTable"), DataTable)
Dim row1 As DataRow = t.NewRow()
row1("ID") = t.Rows.Count + 1
row1("univirsity") = 3
row1("major") = 31
t.Rows.Add(row1)
Session("MyDataTable") = t
GridView1.DataSource = t
GridView1.DataBind()
End Sub
So now what the code does is instantiate a new datatable object as long as we are on the page (first post back) and adds the columns. Once it has defined the data table we throw it in some session state. When you click the add button you cannot in your previous code just keep using dt because dt scope was lost in your prior code. We do this by assigning the sessioned datatable which was stored prior to a temp datatable. We add the row and reset the session that way the next time we add a row it will display the second row, then third row, and so on...
I recommend a good asp.net book on such as Beginning ASP.net 3.5 in C# 2008. There are a ton of vb.net books on the same subject matter.

You need to save the datatable to Session, because local variables are not preserved. So you need to do:
protected override OnLoad(..) //or OnInit
{
dt = Session["DataTable"] as DataTable;
if (dt == null)
{
dt = new DataTable();
//load columns
}
}
protected override OnUnLoad(..)
{
Session["DataTable"] = dt;
}
Session saves the data table reference across postbacks as the web is stateless.

Related

Dynamically create datatable that allows population multiple times

I'm trying to dynamically create a datatable that will allow me to populate single records multiple times when a procedure is executed. I know how to create the datatable with the columns I need but my problem is that every time I execute the sub routine to add a record it re-initializes the datatable and wipes out the previously populated record. How do I create the datatable so that it initializes only once? I've tried initializing during the Page_Load event with a 'Not IsPostback' condition but that doesn't work. Any other ideas?
Partial Public Class ContactLookup
Inherits System.Web.UI.Page
Dim dtContacts As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
dtContacts = New DataTable
dtContacts.Columns.Add("Email", GetType(String))
dtContacts.Columns.Add("AccountNum", GetType(String))
End If
End Sub
Protected Sub btnAddContact_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAddContact.Click
Dim AcctNum As String = txtLocAcct.Text
Dim Email As String = txtEmail.Text
Dim drContacts As DataRow = dtContacts.NewRow
drContacts("Email") = Email
drContacts("AccountNum") = AcctNum
dtContacts.Rows.Add(drContacts)
End Sub
End Class
If I am correct than you need the table returned by the query as datatable. If its so then you can try this. Change your SqlCommand like this,
var dt =new DataTable(); // a new table to populate dynamically.
var reader = cmd.ExecuterReader(CommandBehaviour.SequentialAccess");
dt.Load(reader);
return dt; // now your dt will be query dependent.
Sorry the answer is in C#. You can convert it to VB at http://converter.telerik.com
Updated Answer
In your case i would suggest create a class instead of datatables and datacolumns. See a sample below:
public class Student
{
public string Name{get;set;}
public int Roll{get;set;}
}
In your code behind
private Student _stud = new Student();
private void FillObjects(){
_stud.Name= txtName.Text;
_stud.Roll=Convert.ToInt32(txtRoll.Text);
}
private void ButtonClick{
FillObjects();
YourClass.SaveMethod(_stud);
}

How to add a new record to datagridview control in Visual Basic?

I want to add to my site a simple table/excel-like feauture that will display some values. So, I added a gridview. I don't use Datasets or database biding at all. All I have is a small form with two entries. When the user clicks a button, I want to add some values to the datagridview control as a new row. How do I add a new record to datagridview control in VB.NET?
I have tried this code:
GridView1.Rows.Add(New String() {Value1, Value2})
but I get an error that:
'Add' is not a member of 'System.Web.UI.WebControls.GridViewRowCollection'
My ASPX:
<asp:GridView ID="GridView1" runat="server" Width="731px">
<Columns>
<asp:BoundField HeaderText="Name" />
<asp:BoundField HeaderText="Grade" />
</Columns>
</asp:GridView>
ok. use a datatable like
protected void Page_Load(object sender,EventArgs e)
{
if(!IsPostback)
{
DataTable myDataTable = new DataTable();
DataColumn myDataColumn;
myDataColumn = new DataColumn();
myDataColumn.DataType = Type.GetType("System.String");
myDataColumn.ColumnName = "Value1";
myDataTable.Columns.Add(myDataColumn);
myDataColumn = new DataColumn();
myDataColumn.DataType = Type.GetType("System.String");
myDataColumn.ColumnName = "Value2";
myDataTable.Columns.Add(myDataColumn);
ViewState["Data"]=myDataTable;
}
}
protected void btnAdd(object sender,EventArgs e)
{
Datatable Dt=(Datatable)ViewState["Data"];
DataRow Dr=Dt.NewRow();
Dr[0]=TextBox1.Text;
Dr[1]=TextBox2.Text;
Dt.Rows.Add(Dr);
ViewState["Data"]=Dt;
}
Hope this will help you.
It is pretty easy. All you have to do is to Bind your grid to any Colleciton, such as List, Array, DataTable. Create your record class
Public Class MyRecord
Private _name As String = ""
Private _grade As Integer = ""
Public Property Name() As String
Get
Return Me._name
End Get
Set(ByVal value As String)
Me._name = Value
End Set
End Property
Public Property Grade() As Integer
Get
Return Me._grade
End Get
Set(ByVal value As Integer)
Me._grade = Value
End Set
End Property
End Class
In your Page_Load Bind your grid to List
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPotback Then
Dim list As New List(Of MyRecord)()
list.Add(New MyRecord() With { _
Key .Name = "dsfsdf", _
Key .Grade = 45 _
})
list.Add(New MyRecord() With { _
Key .Name = "dsfsd234f", _
Key .Grade = 50 _
})
Session("MyList") = list
GridView1.DataSource = list
GridView1.DataBind()
End If
End Sub
Then add some form with textboxes and button and handle button on_click event
Protected Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
Dim list As New List(Of MyRecord)
If Session("MyList") Is Not Nothing Then
list = DirectCast(Session("MyList"), List(Of MyRecord))
End If
list.Add(New MyRecord() With { _
Key .Name = txt1.Text, _
Key .Grade = Convert.ToInt32(txt2.Text) _
})
GridView1.DataSource = list
GridView1.DataBind()
End Sub
Sorry if there are any errors, I am a C# developer

refresh gridview after search

I have a search on a grid view which limits the results. I would like the grid view to repopulate with all entries if a. the search box is empty or b. the user hits a button to refresh.
Protected Sub btnSeach_Click(sender As Object, e As EventArgs) Handles btnSeach.Click
StaffDetailsStaffGridView.DataSourceID = ""
StaffDetailsStaffGridView.DataSource = ObjectDataSource1
StaffDetailsStaffGridView.DataBind()
If txtFnameSearch.text = " " Then
StaffDetailsStaffGridView.DataBind()
End If
End Sub
Protected Sub btnRefreshSearch_Click(sender As Object, e As EventArgs) Handles btnRefreshSearch.Click
StaffDetailsStaffGridView.DataBind()
End Sub
End Class
StaffDetailsStaffGridView.DataBind() obviously doesn't work.
how do I do this properly?
The best way to repopulate the GridView is by having a method specifically for binding your data and calling when needed.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostback)
BindGrid();
}
private void BindGrid()
{
StaffDetailsStaffGridView.DataSource = ObjectDataSource1;
StaffDetailsStaffGridView.DataBind();
}
protected void btnRefreshSearch_Click(object sender, EventArgs e)
{
BindGrid();
}
protected void btnSeach_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txtFnameSearch.text))
{
BindGrid();
}
}
I'm assuming you are filtering your data directly via the ObjectDataSource.
You should get the datasource again and set it as the DataSource and then bind again.
Something like this
Protected Sub btnRefreshSearch_Click(sender As Object, e As EventArgs) Handles btnRefreshSearch.Click
Dim searchKey as String
searchKey =txtFnameSearch.Text.Trim()
Dim staffSearchREsults=MyService.GetSearchResults(searchKey)
StaffDetailsStaffGridView.DataSource = staffSearchREsults
StaffDetailsStaffGridView.DataBind()
End Sub
Assuming MyService.GetSearchResults method will return you a valid search result based on the search key.
This will not work because, after postback, gridview's datasource will be lost. So you always need to set datasource before DataBind() is called.
StaffDetailsStaffGridView.DataSource = ObjectDataSource1
StaffDetailsStaffGridView.DataBind()
You can also save ObjectDataSource1 into session and use it later for binding:
Session["MyObjectDataSource"] = ObjectDataSource1;
...
Protected Sub btnRefreshSearch_Click(sender As Object, e As EventArgs) Handles btnRefreshSearch.Click
StaffDetailsStaffGridView.DataSource = Session["MyObjectDataSource"]
StaffDetailsStaffGridView.DataBind()
End Sub
If you're using a declarative datasource, you can just call DataBind() again on the GridView:
StaffDetailsStaffGridView.DataBind()

gridview cell formatting

I have a gridview event OnRowDataBound event handler like this:
protected void MyGridviewEvent(object sender, GridViewRowEventArgs e)
{
if (e.Row.DataItem == "Duration")
{
}
}
This selects the appropriate column in the row. I'd like to change the format of that cell. This cell contains a TimeSpan and I'd like to format it hh:mm.
How's this done?
Thanks.
GridViewRow.DataItem returns the underlying datasource of this row. I doubt that it is a String like Duration. Normally it would be a DataRowView and you can access the datacolumn via index or name. To format a timespan you could use the .net framework 4 ToString version that takes a String with custom format providers. In earlier frameworks you have to do it manually.
VB.Net example(i hope you get it, the important part is the RowDataBound part)
Private Sub BindGrid()
Dim dt As New DataTable
dt.Columns.Add("ID", GetType(Int32)).AutoIncrement = True
dt.Columns.Add("Duration", GetType(TimeSpan))
dt.PrimaryKey = New DataColumn() {dt.Columns("ID")}
Dim newRow As DataRow = dt.NewRow
newRow("ID") = 1
newRow("Duration") = TimeSpan.FromDays(7)
dt.Rows.Add(newRow)
newRow = dt.NewRow
newRow("ID") = 2
newRow("Duration") = TimeSpan.FromMinutes(777)
dt.Rows.Add(newRow)
Me.GridView1.AutoGenerateColumns = True
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
End Sub
Private Sub GridRowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim row As DataRowView = DirectCast(e.Row.DataItem, DataRowView)
Dim duration As TimeSpan = DirectCast(row("Duration"), TimeSpan)
e.Row.Cells(1).Text = String.Format("{0:00}:{1:00}", duration.TotalHours, duration.Minutes)
End If
End Sub
Try something like this
protected void MyGridviewEvent(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TimeSpan ts = TimeSpan.Parse(DataBinder.Eval(e.Row.DataItem, "Duration").ToString());
e.Row.Cells[1].Text = String.Format("{0:t}", ts));
}
}
Where e.Row.Cells[1] is the index of the "Duration" column.

Adding multile row in the girdview

Adding the row one by one in the button click..
(i tried but its overwirting the same row)
Here it is in vb for you. Tested it, seems to work fine. Declare dt as shared
Imports System.Data
Partial Class _Default
Inherits System.Web.UI.Page
Shared dt As DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
dt = New DataTable
dt.Columns.Add("Colum1")
dt.Columns.Add("Colum2")
End If
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
dt.Rows.Add(TextBox1.Text, TextBox2.Text)
GridView1.DataSource = dt
GridView1.DataBind()
End Sub
End Class
A gridview should be bound to a datasource. You'll need to add a record to this datasource and then call myGridView.Bind() to bind to it.
Lots of info on MSDN about GridViews:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.aspx
You can do something like this...
static DataTable dt;
private void Form1_Load(object sender, EventArgs e)
{
dt = new DataTable();
dt.Columns.Add("Colum1");
dt.Columns.Add("Colum2");
}
private void button1_Click(object sender, EventArgs e)
{
dt.Rows.Add(textBox1.Text, textBox2.Text);
dataGridView1.DataSource = dt;
}

Resources