DataBinding on PostBack?

K

Krista Lemieux

I'm new to ASP.NET and I'm not use to the way things are handled with
this technology. I've been told that when I have a control, I should
only bind the data to it once, and not on each post back (basically
have the data binding done in the If NOT IsPostBack Then statement).
How come? How does this information get preserved?

Which raises another question. Becuase I want to get away from the
spaghetti code approach, I would like to create some of the controls
programatically in the code-behind, not the aspx file. Where would I
create that. Well for instance I want to create a table using for
loops (for rows and then for columns), and then bind some data from a
DataTable to this dynamically created table. Would I create the Table
(not the DataTable) in the Page_Load and bind it only once (not on
each postback)??? How does that work.

Any suggestions, or explanations greatly appreciated. Thank you so
much in advance.

Merci,
Krista Lemieux
 
R

Raterus

Krista Lemieux said:
...How does this information get preserved?
ViewState!
Would I create the Table
(not the DataTable) in the Page_Load and bind it only once (not on
each postback)??? How does that work.
Check out the DataGrid control, you can easily bind the information in a datatable to it. No need to create your own table. You would bind this initially when the page first loads, and if something every changed in it (selected a record, went to the next page of results, sort, etc) you would rebind the contents to reflect the new changes.

It'll make sense if you work with it enough, trust me
--Michael
 
K

Krista Lemieux

Thanks for the quick reply Michael

You mentioned to use DataGrid. I'm experimenting with it
currently, but I had a hard time adding columns to it
programatically (or dynamically) so I dropped it. I don't
remember what the exact problem was, but I think it was
something on each postback they waren't appearing
correcly or just not being re-added. Is there a specific
place where I should add the dynamic columns so I have no
problems on post back. I mean should I add them in the
Init section, or the Page_Load (since I can't, or don't
want to put my while loop creating this in the aspx file).

Thank You so much in advance for help.

Merci,
Krista Lemieux
-----Original Message-----


Check out the DataGrid control, you can easily bind the
information in a datatable to it. No need to create your
own table. You would bind this initially when the page
first loads, and if something every changed in it
(selected a record, went to the next page of results,
sort, etc) you would rebind the contents to reflect the
new changes.
 
K

Kyril Magnos

Hi Krista,

Adding columns to the datagrid programmatically is actually pretty easy to
do. Have you looked at the DataGrid's AutoGenerateColumns property? It will
dynamically create columns based on the data source that you use. It's a
nice feature, but does not give much in terms of customization or control.
To dynamically add columns, what you should do is something like below:

<pseudo-code>
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) { BindData(); }
}

private void BindData()
{
//here we will add two columns to our data grid.
//assume the name of the grid is dg

ButtonColumn btnCol = new ButtonColumn();
btnCol.ButtonType = ButtonColumnType.LinkButton;
btnCol.CommandName = "Select";
btnCol.HeaderText = "Select";
btnCol.Text = "Select Item";
dg.Columns.Add(btnCol);

BoundColumn boundCol = new BoundColumn();
boundCol.DataField = "Author";
boundCol.HeaderText = "Authors";
dg.Columns.Add(boundCol);

dg.DataKeyField = "AuthorID";
dg.DataSource = authorsDataTable;
dg.DataBind();
}
</pseudo-code>

Now, this will fire only on the first page load because of the
"if(!Page.IsPostBack)". What you will do now is hook up the datagrid events
so that you can interact with the grid. To trap the click of one of the link
buttons for instance, you can use one of two events in the data grid. Either
the ItemCommand event or the SelectedIndexChanged event. All you have to do
is make sure that anything in your page that will trigger a post back (a
button or a drop down list changing) calls the BindData() method to rebuild
and rebind the data grid. Now, there are a couple of other places that you
can put the column creation code. You can put it in the Page_Load event
handler, before the check for a postback. You can also place it in the
overridden OnInit method.

Like Michael said, given time, you'll pick up the data grid in no time. It
is one of the most flexible (and most complicated) controls in the .NET
Framework, but it pays off. :)

HTH,

Kyril
 
K

Krista Lemieux

Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read the
value from the textbox by getting the CType(e.Item.Cells
(1).Controls(0), TextBox).Text, and then after retrieving
the values I'm caling the BindData function (all of this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux

-----Original Message-----
Hi Krista,

Adding columns to the datagrid programmatically is actually pretty easy to
do. Have you looked at the DataGrid's
AutoGenerateColumns property? It will
 
K

Kyril Magnos

Hi Krista,

Never assume that the TextBox in EditMode is at the beginning of the
Controls collection. ;) Often times, especially if there is text in the cell
or it is a TemplateColumn, the text box may be at position 1 or further down
the chain.

There are two ways that you can accomplish what you want to do. The first
would be to iterate through the Control collection of the cell and test each
control to see if it is a textbox. Otherwise, you can use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#, my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab all the text box
values or you could just call FindControl for each textbox value that you
need.

HTH,

Kyril :)
 
K

Krista Lemieux

Once again Kyril, Thank You for your help. I tried
exactly what you told me with the loop, but the
e.Item.Cells(1).Controls does not return any controls. I
checked the count on this line (e.Item.Cells
(1).Controls.Count) and it gave me 0, but after I do
BindData() (without trying to retrieve the value of the
TextBox), it creates the datagrid fine without any errors
and the same line returns the number of columns that I
programatically added. It seems as if I need to BindData
before I try to retrieve the textbox values, which from
my understanding should not be the case. Is it possible
that I need to create my columns of my DataGrid in a
different place? Becuase right now my created datagrid
columns disapear until I call BindData again. But I would
probably need to do that 2 times on each edit (BindData
before retrieving TextBox values, and the BindData after
modifying the DataTable with the TextBox values). Does
that make sense? Or am I completly off track?

Thank You for your help and time.

Merci,
Krista Lemieux

-----Original Message-----
Hi Krista,

Never assume that the TextBox in EditMode is at the beginning of the
Controls collection. ;) Often times, especially if there is text in the cell
or it is a TemplateColumn, the text box may be at position 1 or further down
the chain.

There are two ways that you can accomplish what you want to do. The first
would be to iterate through the Control collection of the cell and test each
control to see if it is a textbox. Otherwise, you can use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#, my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl ("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl ("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab all the text box
values or you could just call FindControl for each textbox value that you
need.

HTH,

Kyril :)


Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read the
value from the textbox by getting the CType (e.Item.Cells
(1).Controls(0), TextBox).Text, and then after retrieving
the values I'm caling the BindData function (all of this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux


AutoGenerateColumns property? It will that
you use. It's a event.
All you have to do have
no


.
 
K

Kyril Magnos

You are most welcome, Krista.

To the problem at hand:

You have 3 basic options available to you. You can either create the columns
for the data grid in the HTML/ASPX code by using tags (or the visual
designer, which isn't all that bad. Kind of nice to use, actually ;) ), you
can have the columns created in the Page_Load event (by placing the column
generating code before the check for IsPostBack), or in the OnInit() method.
I would dare say that creating the columns in the HTML code is by far the
easiest, but it is also the worst when it comes to maintenance.

Try moving the column generating code to the Page_Load first and see what
happens. Make sure that the columns are created before you check for post
back. I think you should get different results. Sorry if I steered you down
the wrong path earlier... Hindsight is always 20/20... lol

HTH,

Kyril

Krista Lemieux said:
Once again Kyril, Thank You for your help. I tried
exactly what you told me with the loop, but the
e.Item.Cells(1).Controls does not return any controls. I
checked the count on this line (e.Item.Cells
(1).Controls.Count) and it gave me 0, but after I do
BindData() (without trying to retrieve the value of the
TextBox), it creates the datagrid fine without any errors
and the same line returns the number of columns that I
programatically added. It seems as if I need to BindData
before I try to retrieve the textbox values, which from
my understanding should not be the case. Is it possible
that I need to create my columns of my DataGrid in a
different place? Becuase right now my created datagrid
columns disapear until I call BindData again. But I would
probably need to do that 2 times on each edit (BindData
before retrieving TextBox values, and the BindData after
modifying the DataTable with the TextBox values). Does
that make sense? Or am I completly off track?

Thank You for your help and time.

Merci,
Krista Lemieux

-----Original Message-----
Hi Krista,

Never assume that the TextBox in EditMode is at the beginning of the
Controls collection. ;) Often times, especially if there is text in the cell
or it is a TemplateColumn, the text box may be at position 1 or further down
the chain.

There are two ways that you can accomplish what you want to do. The first
would be to iterate through the Control collection of the cell and test each
control to see if it is a textbox. Otherwise, you can use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#, my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl ("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl ("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab all the text box
values or you could just call FindControl for each textbox value that you
need.

HTH,

Kyril :)


Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read the
value from the textbox by getting the CType (e.Item.Cells
(1).Controls(0), TextBox).Text, and then after retrieving
the values I'm caling the BindData function (all of this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Adding columns to the datagrid programmatically is
actually pretty easy to
do. Have you looked at the DataGrid's
AutoGenerateColumns property? It will
dynamically create columns based on the data source that
you use. It's a
nice feature, but does not give much in terms of
customization or control.
To dynamically add columns, what you should do is
something like below:

<pseudo-code>
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) { BindData(); }
}

private void BindData()
{
//here we will add two columns to our data grid.
//assume the name of the grid is dg

ButtonColumn btnCol = new ButtonColumn();
btnCol.ButtonType = ButtonColumnType.LinkButton;
btnCol.CommandName = "Select";
btnCol.HeaderText = "Select";
btnCol.Text = "Select Item";
dg.Columns.Add(btnCol);

BoundColumn boundCol = new BoundColumn();
boundCol.DataField = "Author";
boundCol.HeaderText = "Authors";
dg.Columns.Add(boundCol);

dg.DataKeyField = "AuthorID";
dg.DataSource = authorsDataTable;
dg.DataBind();
}
</pseudo-code>

Now, this will fire only on the first page load because
of the
"if(!Page.IsPostBack)". What you will do now is hook up
the datagrid events
so that you can interact with the grid. To trap the
click of one of the link
buttons for instance, you can use one of two events in
the data grid. Either
the ItemCommand event or the SelectedIndexChanged event.
All you have to do
is make sure that anything in your page that will
trigger a post back (a
button or a drop down list changing) calls the BindData
() method to rebuild
and rebind the data grid. Now, there are a couple of
other places that you
can put the column creation code. You can put it in the
Page_Load event
handler, before the check for a postback. You can also
place it in the
overridden OnInit method.

Like Michael said, given time, you'll pick up the data
grid in no time. It
is one of the most flexible (and most complicated)
controls in the .NET
Framework, but it pays off. :)

HTH,

Kyril

message
Thanks for the quick reply Michael

You mentioned to use DataGrid. I'm experimenting with
it
currently, but I had a hard time adding columns to it
programatically (or dynamically) so I dropped it. I
don't
remember what the exact problem was, but I think it was
something on each postback they waren't appearing
correcly or just not being re-added. Is there a
specific
place where I should add the dynamic columns so I have
no
problems on post back. I mean should I add them in the
Init section, or the Page_Load (since I can't, or don't
want to put my while loop creating this in the aspx
file).

Thank You so much in advance for help.

Merci,
Krista Lemieux

-----Original Message-----

message
...How does this information get preserved?
ViewState!

Would I create the Table
(not the DataTable) in the Page_Load and bind it only
once (not on
each postback)??? How does that work.
Check out the DataGrid control, you can easily bind the
information in a datatable to it. No need to create
your
own table. You would bind this initially when the page
first loads, and if something every changed in it
(selected a record, went to the next page of results,
sort, etc) you would rebind the contents to reflect the
new changes.

It'll make sense if you work with it enough, trust me
--Michael
.



.


.
 
K

Krista Lemieux

Hello Kyril,

I don't think you led me the wrong way, I think I may not
have been clear enough with some things because of lack
of my ASP.NET knowledge... So I appologize for that.

As for the three options I experimented with the three
suggested way, and I had no luck :(... I get the same
error. Basically At first I tried to put the code in the
Page_Load (so that it executes on each postback) and then
only bind the datasource to the datagrid once (not on
each postback)... That didn't work. So then I tried
putting the same code in the Init section, and again no
luck.

In the aspx code, I added few columns by hardcoding them
(in the like HTML syntax), but I still need to add other
columns dynamically, because the number can change down
the road and I do not want to hard code them. So when I
did that, it also worked fine, until when I tried to
access the textbox values through e.Item.Cells
(1).Controls. The only ones I was able to access is the
ones that I defined in the aspx page, but I was not able
to access the ones I created programatically. The
e.Item.Cells(1).Controls.Count returned the number of
columns I created in aspx page. So what I did is, in the
Page_Load I BindData() on each postback (bad practice
from what I heard), and now in the Update function I can
access the text box values through e.Item.Cells
(1).Controls(i), and they are the ones that I entered.
But when I retrieve the Textbox values from the columns I
created in the aspx file, I get the old values (the ones
loaded from the database, not the ones entered in the
textbox). So by calling BindData on each postback I lose
the values from the hardcoded columns. So there is no
winning with this thing... I sure hope that what You and
Mike said is true, that with practice this will become
clearer, cause at this point its fairly discouraging.

Eventhough; I greatly appretiate your help, as you made
awsome suggestions that I learned from. So once again
thank you,


Merci,
Krista Lemieux
-----Original Message-----
You are most welcome, Krista.

To the problem at hand:

You have 3 basic options available to you. You can either create the columns
for the data grid in the HTML/ASPX code by using tags (or the visual
designer, which isn't all that bad. Kind of nice to use, actually ;) ), you
can have the columns created in the Page_Load event (by placing the column
generating code before the check for IsPostBack), or in the OnInit() method.
I would dare say that creating the columns in the HTML code is by far the
easiest, but it is also the worst when it comes to maintenance.

Try moving the column generating code to the Page_Load first and see what
happens. Make sure that the columns are created before you check for post
back. I think you should get different results. Sorry if I steered you down
the wrong path earlier... Hindsight is always 20/20... lol

HTH,

Kyril

Once again Kyril, Thank You for your help. I tried
exactly what you told me with the loop, but the
e.Item.Cells(1).Controls does not return any controls. I
checked the count on this line (e.Item.Cells
(1).Controls.Count) and it gave me 0, but after I do
BindData() (without trying to retrieve the value of the
TextBox), it creates the datagrid fine without any errors
and the same line returns the number of columns that I
programatically added. It seems as if I need to BindData
before I try to retrieve the textbox values, which from
my understanding should not be the case. Is it possible
that I need to create my columns of my DataGrid in a
different place? Becuase right now my created datagrid
columns disapear until I call BindData again. But I would
probably need to do that 2 times on each edit (BindData
before retrieving TextBox values, and the BindData after
modifying the DataTable with the TextBox values). Does
that make sense? Or am I completly off track?

Thank You for your help and time.

Merci,
Krista Lemieux

-----Original Message-----
Hi Krista,

Never assume that the TextBox in EditMode is at the beginning of the
Controls collection. ;) Often times, especially if
there
is text in the cell
or it is a TemplateColumn, the text box may be at position 1 or further down
the chain.

There are two ways that you can accomplish what you
want
to do. The first
would be to iterate through the Control collection of the cell and test each
control to see if it is a textbox. Otherwise, you can use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#, my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl ("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl ("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab all the text box
values or you could just call FindControl for each textbox value that you
need.

HTH,

Kyril :)


Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read the
value from the textbox by getting the CType (e.Item.Cells
(1).Controls(0), TextBox).Text, and then after retrieving
the values I'm caling the BindData function (all of this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Adding columns to the datagrid programmatically is
actually pretty easy to
do. Have you looked at the DataGrid's
AutoGenerateColumns property? It will
dynamically create columns based on the data source that
you use. It's a
nice feature, but does not give much in terms of
customization or control.
To dynamically add columns, what you should do is
something like below:

<pseudo-code>
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) { BindData(); }
}

private void BindData()
{
//here we will add two columns to our data grid.
//assume the name of the grid is dg

ButtonColumn btnCol = new ButtonColumn();
btnCol.ButtonType = ButtonColumnType.LinkButton;
btnCol.CommandName = "Select";
btnCol.HeaderText = "Select";
btnCol.Text = "Select Item";
dg.Columns.Add(btnCol);

BoundColumn boundCol = new BoundColumn();
boundCol.DataField = "Author";
boundCol.HeaderText = "Authors";
dg.Columns.Add(boundCol);

dg.DataKeyField = "AuthorID";
dg.DataSource = authorsDataTable;
dg.DataBind();
}
</pseudo-code>

Now, this will fire only on the first page load because
of the
"if(!Page.IsPostBack)". What you will do now is hook up
the datagrid events
so that you can interact with the grid. To trap the
click of one of the link
buttons for instance, you can use one of two events in
the data grid. Either
the ItemCommand event or the SelectedIndexChanged event.
All you have to do
is make sure that anything in your page that will
trigger a post back (a
button or a drop down list changing) calls the BindData
() method to rebuild
and rebind the data grid. Now, there are a couple of
other places that you
can put the column creation code. You can put it in the
Page_Load event
handler, before the check for a postback. You can also
place it in the
overridden OnInit method.

Like Michael said, given time, you'll pick up the data
grid in no time. It
is one of the most flexible (and most complicated)
controls in the .NET
Framework, but it pays off. :)

HTH,

Kyril

message
Thanks for the quick reply Michael

You mentioned to use DataGrid. I'm experimenting with
it
currently, but I had a hard time adding columns to it
programatically (or dynamically) so I dropped it. I
don't
remember what the exact problem was, but I think it was
something on each postback they waren't appearing
correcly or just not being re-added. Is there a
specific
place where I should add the dynamic columns so I have
no
problems on post back. I mean should I add them in the
Init section, or the Page_Load (since I can't, or don't
want to put my while loop creating this in the aspx
file).

Thank You so much in advance for help.

Merci,
Krista Lemieux

-----Original Message-----

message
...How does this information get preserved?
ViewState!

Would I create the Table
(not the DataTable) in the Page_Load and bind it only
once (not on
each postback)??? How does that work.
Check out the DataGrid control, you can easily bind the
information in a datatable to it. No need to create
your
own table. You would bind this initially when the page
first loads, and if something every changed in it
(selected a record, went to the next page of results,
sort, etc) you would rebind the contents to reflect the
new changes.

It'll make sense if you work with it enough, trust me
--Michael
.



.



.


.
 
K

Kyril Magnos

Hi Krista,

Well, after talking to a few experts here, and also trying quite a few
different things, it looks like your best bet is going to be to go with the
HTML/ASPX option. There is another option, which is deriving a new user
control that inherits from DataGrid and building the columns in the control
with some advanced features. I don't know what your skill level is, so I
can't recommend that as an option.

I would say hard code the columns in the HTML at least until ASP.NET 2.0
comes out. You will have a functional product and if the number of columns
change, that should be a relatively easy thing to maintain. Especially if
your code is written cleanly. You could also do some other advanced features
to help make the maintenance easier, but we can get into those later if you
decide that you would want to do that.

HTH,

Kyril

Krista Lemieux said:
Hello Kyril,

I don't think you led me the wrong way, I think I may not
have been clear enough with some things because of lack
of my ASP.NET knowledge... So I appologize for that.

As for the three options I experimented with the three
suggested way, and I had no luck :(... I get the same
error. Basically At first I tried to put the code in the
Page_Load (so that it executes on each postback) and then
only bind the datasource to the datagrid once (not on
each postback)... That didn't work. So then I tried
putting the same code in the Init section, and again no
luck.

In the aspx code, I added few columns by hardcoding them
(in the like HTML syntax), but I still need to add other
columns dynamically, because the number can change down
the road and I do not want to hard code them. So when I
did that, it also worked fine, until when I tried to
access the textbox values through e.Item.Cells
(1).Controls. The only ones I was able to access is the
ones that I defined in the aspx page, but I was not able
to access the ones I created programatically. The
e.Item.Cells(1).Controls.Count returned the number of
columns I created in aspx page. So what I did is, in the
Page_Load I BindData() on each postback (bad practice
from what I heard), and now in the Update function I can
access the text box values through e.Item.Cells
(1).Controls(i), and they are the ones that I entered.
But when I retrieve the Textbox values from the columns I
created in the aspx file, I get the old values (the ones
loaded from the database, not the ones entered in the
textbox). So by calling BindData on each postback I lose
the values from the hardcoded columns. So there is no
winning with this thing... I sure hope that what You and
Mike said is true, that with practice this will become
clearer, cause at this point its fairly discouraging.

Eventhough; I greatly appretiate your help, as you made
awsome suggestions that I learned from. So once again
thank you,


Merci,
Krista Lemieux
-----Original Message-----
You are most welcome, Krista.

To the problem at hand:

You have 3 basic options available to you. You can either create the columns
for the data grid in the HTML/ASPX code by using tags (or the visual
designer, which isn't all that bad. Kind of nice to use, actually ;) ), you
can have the columns created in the Page_Load event (by placing the column
generating code before the check for IsPostBack), or in the OnInit() method.
I would dare say that creating the columns in the HTML code is by far the
easiest, but it is also the worst when it comes to maintenance.

Try moving the column generating code to the Page_Load first and see what
happens. Make sure that the columns are created before you check for post
back. I think you should get different results. Sorry if I steered you down
the wrong path earlier... Hindsight is always 20/20... lol

HTH,

Kyril

Once again Kyril, Thank You for your help. I tried
exactly what you told me with the loop, but the
e.Item.Cells(1).Controls does not return any controls. I
checked the count on this line (e.Item.Cells
(1).Controls.Count) and it gave me 0, but after I do
BindData() (without trying to retrieve the value of the
TextBox), it creates the datagrid fine without any errors
and the same line returns the number of columns that I
programatically added. It seems as if I need to BindData
before I try to retrieve the textbox values, which from
my understanding should not be the case. Is it possible
that I need to create my columns of my DataGrid in a
different place? Becuase right now my created datagrid
columns disapear until I call BindData again. But I would
probably need to do that 2 times on each edit (BindData
before retrieving TextBox values, and the BindData after
modifying the DataTable with the TextBox values). Does
that make sense? Or am I completly off track?

Thank You for your help and time.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Never assume that the TextBox in EditMode is at the
beginning of the
Controls collection. ;) Often times, especially if there
is text in the cell
or it is a TemplateColumn, the text box may be at
position 1 or further down
the chain.

There are two ways that you can accomplish what you want
to do. The first
would be to iterate through the Control collection of
the cell and test each
control to see if it is a textbox. Otherwise, you can
use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#,
my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a
text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl
("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl
("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab
all the text box
values or you could just call FindControl for each
textbox value that you
need.

HTH,

Kyril :)


message
Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error
in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read
the
value from the textbox by getting the CType
(e.Item.Cells
(1).Controls(0), TextBox).Text, and then after
retrieving
the values I'm caling the BindData function (all of
this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Adding columns to the datagrid programmatically is
actually pretty easy to
do. Have you looked at the DataGrid's
AutoGenerateColumns property? It will
dynamically create columns based on the data source
that
you use. It's a
nice feature, but does not give much in terms of
customization or control.
To dynamically add columns, what you should do is
something like below:

<pseudo-code>
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) { BindData(); }
}

private void BindData()
{
//here we will add two columns to our data grid.
//assume the name of the grid is dg

ButtonColumn btnCol = new ButtonColumn();
btnCol.ButtonType = ButtonColumnType.LinkButton;
btnCol.CommandName = "Select";
btnCol.HeaderText = "Select";
btnCol.Text = "Select Item";
dg.Columns.Add(btnCol);

BoundColumn boundCol = new BoundColumn();
boundCol.DataField = "Author";
boundCol.HeaderText = "Authors";
dg.Columns.Add(boundCol);

dg.DataKeyField = "AuthorID";
dg.DataSource = authorsDataTable;
dg.DataBind();
}
</pseudo-code>

Now, this will fire only on the first page load because
of the
"if(!Page.IsPostBack)". What you will do now is hook up
the datagrid events
so that you can interact with the grid. To trap the
click of one of the link
buttons for instance, you can use one of two events in
the data grid. Either
the ItemCommand event or the SelectedIndexChanged
event.
All you have to do
is make sure that anything in your page that will
trigger a post back (a
button or a drop down list changing) calls the BindData
() method to rebuild
and rebind the data grid. Now, there are a couple of
other places that you
can put the column creation code. You can put it in the
Page_Load event
handler, before the check for a postback. You can also
place it in the
overridden OnInit method.

Like Michael said, given time, you'll pick up the data
grid in no time. It
is one of the most flexible (and most complicated)
controls in the .NET
Framework, but it pays off. :)

HTH,

Kyril

message
Thanks for the quick reply Michael

You mentioned to use DataGrid. I'm experimenting with
it
currently, but I had a hard time adding columns to it
programatically (or dynamically) so I dropped it. I
don't
remember what the exact problem was, but I think it
was
something on each postback they waren't appearing
correcly or just not being re-added. Is there a
specific
place where I should add the dynamic columns so I
have
no
problems on post back. I mean should I add them in
the
Init section, or the Page_Load (since I can't, or
don't
want to put my while loop creating this in the aspx
file).

Thank You so much in advance for help.

Merci,
Krista Lemieux

-----Original Message-----

message

...How does this information get preserved?
ViewState!

Would I create the Table
(not the DataTable) in the Page_Load and bind it
only
once (not on
each postback)??? How does that work.
Check out the DataGrid control, you can easily bind
the
information in a datatable to it. No need to create
your
own table. You would bind this initially when the
page
first loads, and if something every changed in it
(selected a record, went to the next page of results,
sort, etc) you would rebind the contents to reflect
the
new changes.

It'll make sense if you work with it enough, trust me
--Michael
.



.



.


.
 
K

Krista Lemieux

Hello Kyril,

Ok... For now I'll take your advice to hard code the
columns. I guess DataGrid is not as flexible as Microsoft
says it is :(... Hopefully as I advance my knowledge
in .NET I will try to figure out a better workaround.
But before I do that, there might be one more thing I
would like to try. Michael said that everything on the
form is saved in the ViewState. So let's say I am editing
a row in the DataGrid, and then hit update. Before I call
the BindData function in the Page_Load, can I somehow get
the values of the TextBoxes of the DataGrid row I was
editing in there (Page_Load)? If I could, that would solve
the problem in a way. I would still need to BindData on
each postback, but at least it would work.


Thank you so much for all of your help and time,


Merci,
Krista Lemieux
-----Original Message-----
Hi Krista,

Well, after talking to a few experts here, and also trying quite a few
different things, it looks like your best bet is going to be to go with the
HTML/ASPX option. There is another option, which is deriving a new user
control that inherits from DataGrid and building the columns in the control
with some advanced features. I don't know what your skill level is, so I
can't recommend that as an option.

I would say hard code the columns in the HTML at least until ASP.NET 2.0
comes out. You will have a functional product and if the number of columns
change, that should be a relatively easy thing to maintain. Especially if
your code is written cleanly. You could also do some other advanced features
to help make the maintenance easier, but we can get into those later if you
decide that you would want to do that.

HTH,

Kyril

Hello Kyril,

I don't think you led me the wrong way, I think I may not
have been clear enough with some things because of lack
of my ASP.NET knowledge... So I appologize for that.

As for the three options I experimented with the three
suggested way, and I had no luck :(... I get the same
error. Basically At first I tried to put the code in the
Page_Load (so that it executes on each postback) and then
only bind the datasource to the datagrid once (not on
each postback)... That didn't work. So then I tried
putting the same code in the Init section, and again no
luck.

In the aspx code, I added few columns by hardcoding them
(in the like HTML syntax), but I still need to add other
columns dynamically, because the number can change down
the road and I do not want to hard code them. So when I
did that, it also worked fine, until when I tried to
access the textbox values through e.Item.Cells
(1).Controls. The only ones I was able to access is the
ones that I defined in the aspx page, but I was not able
to access the ones I created programatically. The
e.Item.Cells(1).Controls.Count returned the number of
columns I created in aspx page. So what I did is, in the
Page_Load I BindData() on each postback (bad practice
from what I heard), and now in the Update function I can
access the text box values through e.Item.Cells
(1).Controls(i), and they are the ones that I entered.
But when I retrieve the Textbox values from the columns I
created in the aspx file, I get the old values (the ones
loaded from the database, not the ones entered in the
textbox). So by calling BindData on each postback I lose
the values from the hardcoded columns. So there is no
winning with this thing... I sure hope that what You and
Mike said is true, that with practice this will become
clearer, cause at this point its fairly discouraging.

Eventhough; I greatly appretiate your help, as you made
awsome suggestions that I learned from. So once again
thank you,


Merci,
Krista Lemieux
-----Original Message-----
You are most welcome, Krista.

To the problem at hand:

You have 3 basic options available to you. You can either create the columns
for the data grid in the HTML/ASPX code by using tags (or the visual
designer, which isn't all that bad. Kind of nice to use, actually ;) ), you
can have the columns created in the Page_Load event (by placing the column
generating code before the check for IsPostBack), or in the OnInit() method.
I would dare say that creating the columns in the HTML code is by far the
easiest, but it is also the worst when it comes to maintenance.

Try moving the column generating code to the Page_Load first and see what
happens. Make sure that the columns are created before you check for post
back. I think you should get different results. Sorry if I steered you down
the wrong path earlier... Hindsight is always 20/20... lol

HTH,

Kyril

Once again Kyril, Thank You for your help. I tried
exactly what you told me with the loop, but the
e.Item.Cells(1).Controls does not return any controls. I
checked the count on this line (e.Item.Cells
(1).Controls.Count) and it gave me 0, but after I do
BindData() (without trying to retrieve the value of the
TextBox), it creates the datagrid fine without any errors
and the same line returns the number of columns that I
programatically added. It seems as if I need to BindData
before I try to retrieve the textbox values, which from
my understanding should not be the case. Is it possible
that I need to create my columns of my DataGrid in a
different place? Becuase right now my created datagrid
columns disapear until I call BindData again. But I would
probably need to do that 2 times on each edit (BindData
before retrieving TextBox values, and the BindData after
modifying the DataTable with the TextBox values). Does
that make sense? Or am I completly off track?

Thank You for your help and time.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Never assume that the TextBox in EditMode is at the
beginning of the
Controls collection. ;) Often times, especially if there
is text in the cell
or it is a TemplateColumn, the text box may be at
position 1 or further down
the chain.

There are two ways that you can accomplish what you want
to do. The first
would be to iterate through the Control collection of
the cell and test each
control to see if it is a textbox. Otherwise, you can
use the FindControl
method to locate the textbox by ID.

Something like this: (forgive me for doing this in C#,
my VB.NET is really
rusty!)

<pseudo-code>
//This code snippet loops through the cell's controls
//collection and tests each control to see if it is a
text box
foreach(Control c in e.Item.Cells[1].Controls)
{
if(c is TextBox)
{
//grab the value of this text box...
string text = ((TextBox)c).Text;
}
}

//This is the FindControl method at work
TextBox tempText = (TextBox)dataGrid.FindControl
("TextBoxName");
if(tempText != null)
{
//do something here...
}

In VB.NET, I think it would be
'This is the same loop as above.
For Each c In e.Item.Cells[1].Controls
If c Is TextBox Then
Dim text As String = (CType(c, TextBox)).Text
End If
Next

'This is the FindControl method at work
Dim tempText as TextBox = CType(dataGrid.FindControl
("TextBoxName"),
TextBox)
If tempText IsNot Nothing Then
'Do something here
End if

</pseudo-code>

You could loop through all the cells this way and grab
all the text box
values or you could just call FindControl for each
textbox value that you
need.

HTH,

Kyril :)


message
Thank you for your help Kyril. I tried the code (your
pseudo) on my page with my datagrid. Everything worked
great except one thing... I tried combining your code
with a code that I saw in a book, so that I can edit a
row and update it. Basically when I click the Edit link
it shows the selected row in the edit mode (textboxes),
but when I try to update my changes (by clicking the
Update Link) it gives me an Index out of bounds error
in
the Update button function. It is as if the columns no
longer exist. Like in the example I'm trying to read
the
value from the textbox by getting the CType
(e.Item.Cells
(1).Controls(0), TextBox).Text, and then after
retrieving
the values I'm caling the BindData function (all of
this
is in the Update button function). Am I doing something
wrong that I cannot access the values of the textboxes?

Thank you very much for the help.

Merci,
Krista Lemieux


-----Original Message-----
Hi Krista,

Adding columns to the datagrid programmatically is
actually pretty easy to
do. Have you looked at the DataGrid's
AutoGenerateColumns property? It will
dynamically create columns based on the data source
that
you use. It's a
nice feature, but does not give much in terms of
customization or control.
To dynamically add columns, what you should do is
something like below:

<pseudo-code>
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack) { BindData(); }
}

private void BindData()
{
//here we will add two columns to our data grid.
//assume the name of the grid is dg

ButtonColumn btnCol = new ButtonColumn();
btnCol.ButtonType = ButtonColumnType.LinkButton;
btnCol.CommandName = "Select";
btnCol.HeaderText = "Select";
btnCol.Text = "Select Item";
dg.Columns.Add(btnCol);

BoundColumn boundCol = new BoundColumn();
boundCol.DataField = "Author";
boundCol.HeaderText = "Authors";
dg.Columns.Add(boundCol);

dg.DataKeyField = "AuthorID";
dg.DataSource = authorsDataTable;
dg.DataBind();
}
</pseudo-code>

Now, this will fire only on the first page load because
of the
"if(!Page.IsPostBack)". What you will do now is hook up
the datagrid events
so that you can interact with the grid. To trap the
click of one of the link
buttons for instance, you can use one of two events in
the data grid. Either
the ItemCommand event or the SelectedIndexChanged
event.
All you have to do
is make sure that anything in your page that will
trigger a post back (a
button or a drop down list changing) calls the BindData
() method to rebuild
and rebind the data grid. Now, there are a couple of
other places that you
can put the column creation code. You can put it in the
Page_Load event
handler, before the check for a postback. You can also
place it in the
overridden OnInit method.

Like Michael said, given time, you'll pick up the data
grid in no time. It
is one of the most flexible (and most complicated)
controls in the .NET
Framework, but it pays off. :)

HTH,

Kyril

message
Thanks for the quick reply Michael

You mentioned to use DataGrid. I'm experimenting with
it
currently, but I had a hard time adding columns to it
programatically (or dynamically) so I dropped it. I
don't
remember what the exact problem was, but I think it
was
something on each postback they waren't appearing
correcly or just not being re-added. Is there a
specific
place where I should add the dynamic columns so I
have
no
problems on post back. I mean should I add them in
the
Init section, or the Page_Load (since I can't, or
don't
want to put my while loop creating this in the aspx
file).

Thank You so much in advance for help.

Merci,
Krista Lemieux

-----Original Message-----

message

...How does this information get preserved?
ViewState!

Would I create the Table
(not the DataTable) in the Page_Load and bind it
only
once (not on
each postback)??? How does that work.
Check out the DataGrid control, you can easily bind
the
information in a datatable to it. No need to create
your
own table. You would bind this initially when the
page
first loads, and if something every changed in it
(selected a record, went to the next page of results,
sort, etc) you would rebind the contents to reflect
the
new changes.

It'll make sense if you work with it enough, trust me
--Michael
.



.



.



.


.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

DataBinding 0
DataBinding 0
Repeater DataBinding on PostBack and base.DataBind() 1
DataBinding 1
repeater and databinding (postback) 1
Databinding 1
Help on simple databinding ??? 2
Complex databinding 1

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top