Controls?

A

Arpan

Consider the following code which retrieves data from a SQL Server 2005
DB table & displays it in a DataGrid:

<script runat="server">
Sub Page_Load(ByVal obj As Object, ByVal ea As EventArgs)
Dim dSet As DataSet
Dim sqlConn As SqlConnection
Dim sqlDapter As SqlDataAdapter

sqlConn = New SqlConnection("Data Source=AD\SQLEXPRESS;Initial
Catalog=MyDB;Integrated Security=True")
sqlDapter = New SqlDataAdapter("SELECT * FROM Users", sqlConn)

dSet = New DataSet()
sqlDapter.Fill(dSet, "Users")

dgUsers.DataSource = dSet.Tables("Users").DefaultView
dgUsers.DataBind()
End Sub

Sub EditUsers(ByVal obj As Object, ByVal ea As
DataGridCommandEventArgs)
dgUsers.EditItemIndex = ea.Item.ItemIndex
dgUsers.DataBind()

Response.Write(Control0: ")
Response.Write(ea.Item.Cells(0).Controls(0))

Response.Write("<br>Control1: ")
Response.Write(ea.Item.Cells(0).Controls(1))

Response.Write("<br>Control2: ")
Response.Write(ea.Item.Cells(0).Controls(2))

'Response.Write("<br>Control3: ")
'Response.Write(ea.Item.Cells(0).Controls(3))
End Sub
</script>

<form runat="server">
<asp:DataGrid ID="dgUsers" OnEditCommand="EditUsers"
AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateColumn HeaderText="NAME">
<ItemTemplate>
<asp:Label ID="lblName" runat="server"><%#
Container.DataItem("FirstName") %>&nbsp;<%#
Container.DataItem("LastName") %></asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn HeaderText="ADDRESS" DataField="Address"/>
<asp:BoundColumn HeaderText="CITY" DataField="City"/>
<asp:BoundColumn HeaderText="STATE" DataField="State"/>
<asp:BoundColumn HeaderText="ZIP" DataField="Zip"/>
<asp:EditCommandColumn HeaderText="EDIT" CancelText="CANCEL"
EditText="EDIT" UpdateText="UPDATE"/>
</Columns>
</asp:DataGrid>
</form>

Assume that the DataGrid displays 5 records. When I click the "Edit"
link corresponding to the, say, 1st record, apart from all fields
(editable & non-editable) displayed in the DataGrid, the first 3 pairs
of Response.Write lines within the sub "EditUsers" produce the
following output:

Control0: System.Web.UI.LiteralControl
Control1: System.Web.UI.WebControls.Label
Control2: System.Web.UI.LiteralControl

Can someone please explain me why/how do the first 3 pairs of
Response.Write lines in the sub "EditUsers" produce the above output?

Secondly, note that the last pair of Response.Write lines in the sub
"EditUsers" is commented. If this pair of Response.Write lines are
uncommented, then the following error gets generated:

Specified argument was out of the range of valid values.
Parameter name: index

pointing to this line:

Response.Write(ea.Item.Cells(0).Controls(3))

I couldn't exactly follow why the above Response.Write generates the
above-mentioned error. Can someone please explain me the cause of the
error?

Thanks,

Arpan
 
G

Guest

Firstly:
You are returning the Object not its value.
Assuming you know this, Literal Controls are generally HTML Tags while Web
Controls are standard ASP.NET controls.

Secondly:
Because the Object does not exist!
If you are trying to look at the next cell you need to increment the cell
number.
 
A

Arpan

Because the Object does not exist!

But why doesn't the object exist? When the DataGrid is in the editable
mode, it will display 5 columns - NAME, ADDRESS, CITY, STATE & ZIP plus
the EDIT column (which will display the 2 links - UPDATE & CANCEL for
that row whose EDIT link has been clicked) i.e. in total there are 6
columns. Now if I add the line

Response.Write("Control Count: " & ea.Item.Controls.Count)

in the "EditUsers" sub (which will be raised by the EditCommand event),
the control count comes to 6. So how come the object doesn't exist &
the line

Response.Write(ea.Item.Cells(0).Controls(3))

generates the error? Please clarify this.

Thanks,

Arpan
 
G

Guest

I rarely use the Microsoft grid (Use 3rd Party Grids), but the way I
understand it is: Item equates to the Row and Cell equates to the Column.
Therefore you are only returning the controls contained in your template item.

To see the controls in your Address field you should use:
Response.Write(ea.Item.Cells(1).Controls(0))

To see the number of controls in your cell: (Should be 3)
Response.Write(“Control Count: †& ea.Item.Cells(0).Controls.Count)

Do you understand what I am getting at?
 
A

Arpan

Response.Write("Control Count: " & ea.Item.Cells(0).Controls.Count)

Yeah, you are right......it comes to 3 but how are you getting 3?
Please explain me this.
To see the controls in your Address field you should use:
Response.Write(ea.Item.Cells(1).Controls(0))

Why are you using Controls(0) here? Why not Controls(1) or Controls(2)?

To be honest, I am new to all these things.......so please help me out.

Thanks,

Regards,

Arpan
 
A

Arpan

Item equates to the Row and Cell equates to the Column.

Assume that 5 records have been retrieved from the backend. Since you
say that item equates to row, the no. of items would be 5. Since cell
equates to column, it means there are 6 cells as there are 6 columns
(NAME, ADDRESS, CITY, STATE, ZIP & EDIT). So where from are you getting
3?

Arpan
 
G

Guest

In your first post you mentioned that it contained 2 Literal and 1 Label
control. I’m guessing its 3 because the asp.net label is probably contained
in some kind of wrapper like a Div in order to be inserted into the cell.
You’ll need to look at the content of the two Literal controls to confirm
this!

I only used Controls(0) as an example, there may be additional controls in
the Cell. To check use: ea.Item.Cells(1).Controls.Count

In summary:
ea.Item.Controls should contain the Cells (Row/Column Intersections)
ea.Item.Cells(0).Controls should contain the Controls inside the first Cell
ea.Item.Cells(1).Controls should contain the Controls inside the second Cell

Remember that you are looking at Controls nested inside Controls!

Hope this helps?
 
A

Arpan

Neverlyn, this is what I did now (for the 6 cells/columns):

Response.Write("<br>" & ea.Item.Cells(0).Controls.Count)
Response.Write("<br>" & ea.Item.Cells(1).Controls.Count)
Response.Write("<br>" & ea.Item.Cells(2).Controls.Count)
Response.Write("<br>" & ea.Item.Cells(3).Controls.Count)
Response.Write("<br>" & ea.Item.Cells(4).Controls.Count)
Response.Write("<br>" & ea.Item.Cells(5).Controls.Count)

As I had already pointed out, the DataGrid displays 5 records i.e. 5
rows (excluding the header). Now the output of all the above lines,
when the 1st row in the DataGrid (of course, it can be any row) was in
the editable mode, was

3
0
0
0
0
1

I just don't understand where from is this 3 coming! The 1st
cell/column whose header is "NAME" (which is 0-indexed) has 5 Label
controls (for 5 records). The 2nd cell/column with the header "ADDRESS"
(whose index is 1) also has 5 records wherein the very 1st record is in
the editable mode. Similarly the 3rd cell/column whose header is "CITY"
(whose index is 2), also has 5 records wherein the 1st record is in
the editable mode. The 4th cell/column, whose header is "STATE" & whose
index is 3, also has 5 records wherein the 1st record is in the
editable mode. Then comes the 5th cell/column, whose header is "ZIP" &
whose index is 4, also has 5 records wherein the 1st record is in the
editable mode. Finally comes the 6th & the last cell/column - the text
for the 1st record shows 2 links - "UPDATE" & "CANCEL" whereas the rest
of the rows under this last column show the link "EDIT".

So how does the Control count evaluate to 3? Doesn't ASP.NET consider
the TextBoxes meant for editing as controls?

I hope I have made myself clearer.

Arpan
 
G

Guest

Hi Arpan,

I’m not an expert on the Microsoft Grid, but looking at your results it
appears as though the Cell Controls only contain custom controls you have
added to the grid.

Cell(0) is a Template Column so it is understandable that it contains 3
Controls. Literals on either end (for the wrapper) plus the Label control.

Cell(5) is a type of system handled custom column, which means that it
wouldn’t need a wrapper. (Hence 1 Control)

The other columns are DataBound so there should be no controls here.

As for the number of rows (records), that’s irrelevant because you are only
ever working with a single row.

Also note, I don’t think being in edit mode makes a difference to the number
of controls in the collection. What it shows is only relevant to what you
have between your column tags. (Bound Columns, Templates, etc…)

Does this make things a little clearer?
 
A

Arpan

No Neverlyn, that still doesn't make things clearer for me.
Cell(0) is a Template Column so it is understandable that it contains 3
Controls. Literals on either end (for the wrapper) plus the Label control.

That's right.....Cell(0) is indeed a TemplateColumn (as shown in post
#1) but how do you understand that it contains 3 Controls? The Label
Control in Cell(0) renders the names of the users in the DataGrid -
that's one of the 3 Controls but which are the other 2 Literals you are
referring to on either end?

Arpan
 
G

Guest

As I stated in one of my earlier responses Literal controls are basically
plain HTML controls. My assumption is that template items need to be
contained in some type of <Div> or <Table> and that is why the Literal
controls are there.

If the Literal controls are not a wrapper (e.g. <Div>, <Table>, etc…) then
they must represent something else such as a white space. When debugging,
take a look at the contents of the literal controls. This should give you
some insight into what is happening. Post your findings, I’m sure others
will find them interesting too…

Cheers,
Brad
 
A

Arpan

Brad, since the controls count evaluates to 3, can't you just point out
the 3 controls with the code in post #1? One of the 3 controls is the
Label Control - which are the other 2 Literal controls? All the data
under the first column named "NAME" are within the <span> tag when I
had a look at the source of the page. Just forget about the <div> etc.
tags. Just tell me which lines in the code shown in post #1 are
creating the 2 Literal controls?

Will you please do me a favor? Just copy & paste the code in post #1,
create a new DB table with the columns ID, FirstName, LastName,
Address, City, State & Zip fields, insert 2-3 records in that table &
then run the ASPX page (it won't take much of your time). I am sure you
will get the controls count as 3. Atleast now I feel you will be in a
position to tell me apart from the Label control, what are the other 2
Literal controls.

I was under the impression that this must a basic question as far as
DataGrids are concerned & hence thought that since MVPs & experts
answer in this newsgroup, getting a concrete response from someone or
the other wouldn't take a long time but I guess I was wrong! This is
the 3rd day I am on the lookout for a concrete answer to my question
but still haven't got one. I have asked the same question in some other
ASP.NET forums as well but the situation is the same there as well -
nobody could clarify my doubts yet.

Is my question really so hard to answer? I don't think so! Honestly
speaking, I have just got fed up with this topic.

Arpan
 
G

Guest

I took a quick look at your code running. It is putting a Literal between
each .Net control. Hence this appears to be some sort of separation
mechanism. I can’t be sure exactly why they are doing this, as I didn’t
design their controls.

Why does it matter that they are adding Literals to separate controls in
their template columns? Are the literals stopping you from doing anything in
particular?
 
A

Arpan

I took a quick look at your code running. It is putting a Literal between
each .Net control.

Do you mean to say that a Literal control is being put - one before the
Label control & the other after the Label control.....something like
this:

Literal Control -----> Label -----> Literal Control

which is why the controls count evaluates to 3? I believe that is what
exactly happens by doing a few tests. Keeping the code that I cited in
post #1 as it is, if I add another Label control immediately after the
Label whose ID is lblName under the same TemplateColumn to make the
TemplateColumn look like this:

<asp:TemplateColumn HeaderText="NAME">
<ItemTemplate>
<asp:Label ID="lblName" runat="server"><%#
Container.DataItem("FirstName") %> <%# Container.DataItem("LastName")
%></asp:Label>
<asp:Label ID="lblMidName" runat="server"><%#
Container.DataItem("MidName") %></asp:Label>
</ItemTemplate>
</asp:TemplateColumn>

The Controls count now becomes 5 i.e. apart from the new Label control
that gets added to the Controls Collection, another Literal control
also gets added to the Controls Collection. Note that though I added
only one new Label control in the DataGrid, a Literal control also gets
added to the Controls Collection which makes the Controls count compute
to 5! Adding the new Label must be resulting in something like this
(continuing the graphical representation shown above)

Literal Control -----> Label -----> Literal Control -----> Label ----->
Literal Control

Keeping the 2 Label controls as it is & adding a LinkButton control
changes the controls count from 5 to 7 i.e. it results in

Literal Control -----> Label -----> Literal Control -----> Label ----->
Literal Control -----> LinkBuuton -----> Literal Control

I believe this is what exactly happens. Please do correct me if I am
wrong.
Why does it matter that they are adding Literals to separate controls in
their template columns? Are the literals stopping you from doing anything in
particular?

No, the Literals aren't stopping me from doing what I want to do. I am
of the opinion that I should be well versed with the basic concepts of
DataGrid (or whatever I learn). Coupled with this is my inquisitiveness
that made me post this question.

Arpan
 
G

Guest

That is exactly the same thing I found. Looking at the literal controls
through the debugger, it’s difficult to know exactly why they are there.
Maybe you should post another thread specifically asking why literal controls
are inserted inside template plate column cells. Maybe a MVP or Microsoft
employee will see it and give you more insight?
 
A

Arpan

Neverlyn, here's another example wherein I am creating a DataSet &
binding the data to a DataGrid:

<script runat="server">
Function CreateDataSet() As DataSet
Dim iCount As Integer
Dim arrColors() As String

If (ViewState("Colors") Is Nothing) Then
arrColors = New String(6) {"beige", "lightblue",
"floralwhite", "lavender", "lightyellow", "bisque", "white"}
ViewState("Colors") = arrColors
Else
arrColors = ViewState("Colors")
End If

'create an empty DataSet
Dim dSet As DataSet
dSet = New DataSet("MyDataSet")

'create a new table & columns
Dim dTable As New DataTable("Colors")
dTable.Columns.Add("Color", GetType(String))
dTable.Columns.Add("ID", GetType(Int32))

'add the table to the DataSet's "Tables" collection object
dSet.Tables.Add(dTable)

'add rows to this new table
For iCount = 0 To UBound(arrColors)
Dim dRows As DataRow = dTable.NewRow()
dRows(0) = arrColors(iCount).ToString
dRows(1) = iCount
dTable.Rows.Add(dRows)
Next

Return dSet
End Function

Dim dSet As DataSet
Dim blnSet As Boolean = False

Sub Page_Load(ByVal obj As Object, ByVal ea As EventArgs)
dSet = CreateDataSet()
blnSet = True
If Not (Page.IsPostBack) Then
BindGrid()
End If
End Sub

Sub BindGrid()
dgColors.DataSource = dSet.Tables("Colors").DefaultView
DataBind()
End Sub

Sub ChangeColor(ByVal obj As Object, ByVal ea As
DataGridItemEventArgs)
Dim intIndex As Integer = ea.Item.ItemIndex

If (blnSet) Then
If (intIndex > 0) Then
dgColors.Items(intIndex - 1).BackColor =
Drawing.Color.FromName(dSet.Tables("Colors").Rows(intIndex -
1)("Color"))
End If
End If
End Sub

Sub EditColor(ByVal obj As Object, ByVal ea As
DataGridCommandEventArgs)
dgColors.EditItemIndex = ea.Item.ItemIndex
BindGrid()
Response.Write("Controls Count Edit: " &
ea.Item.Cells(0).Controls.Count & "<br>")
End Sub

Sub CancelColor(ByVal obj As Object, ByVal ea As
DataGridCommandEventArgs)
dgColors.EditItemIndex = -1
BindGrid()
End Sub

Sub UpdateColor(ByVal obj As Object, ByVal ea As
DataGridCommandEventArgs)
Dim strColor As String = CType(ea.Item.Cells(1).Controls(0),
TextBox).Text
dSet.Tables("Colors").Rows(ea.Item.ItemIndex)("Color") =
strColor
ViewState("Colors")(ea.Item.ItemIndex) = strColor
Response.Write("Controls Count Update: " &
ea.Item.Cells(0).Controls.Count & "<br>")
dgColors.EditItemIndex = -1
BindGrid()
End Sub
</script>
<body>
<form runat="server">
<asp:DataGrid ID="dgColors" OnCancelCommand="CancelColor"
OnEditCommand="EditColor" OnItemCreated="ChangeColor"
OnUpdateCommand="UpdateColor" AutoGenerateColumns="false"
runat="server">
<Columns>
<asp:TemplateColumn HeaderText="ID">
<ItemTemplate>
<asp:Label ID="lblID" runat="server"><%# Container.DataItem("ID")
%></asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="Color" HeaderText="COLOR"/>
<asp:EditCommandColumn HeaderText="CHANGE" EditText="EDIT"
UpdateText="CHANGE" CancelText="CANCEL"/>
</Columns>
</asp:DataGrid>
</form>

The DataGrid shows 3 columns with the headers - ID, COLOR & CHANGE.
When the EDIT link under the CHANGE column is clicked, 2 links come up
in the 3rd column - CHANGE & CANCEL & the item corresponding to the
link clicked changes to a TextBox in the 2nd column.

Note the 2 Response.Write lines in the subs "EditColor" &
"UpdateColor". Suppose I click the EDIT link corresponding to the 1st
row (which is beige). Under such circumstances, the Controls count
generated by the sub "EditColor" comes to 3. If I change the color &
then click the CHANGE link in the 3rd column, the Controls count
generated by the sub "UpdateColor" also comes to 3. How is the
controls count coming to 3?

If the Cells(0) in the 2 Response.Write lines under the subs
"EditColor" & "UpdateColor" is changed to Cells(1) i.e. the 2 lines
look like this

Response.Write("Controls Count Update: " &
ea.Item.Cells(1).Controls.Count & "<br>")

then when the DataGrid is in the editable mode (user can change the
color using the TextBox), the controls count comes to 0. If the color
in the TextBox is changed & the CHANGE link is clicked, the controls
count now comes to 1. Why?

Next if the Cells(1) in the 2 Response.Write lines under the subs
"EditColor" & "UpdateColor" is changed to Cells(2) i.e. the 2 lines
look like this

Response.Write("Controls Count Update: " &
ea.Item.Cells(2).Controls.Count & "<br>")

then when the DataGrid is in the editable mode (user can change the
color using the TextBox), the controls count comes to 1. If the color
in the TextBox is changed & the CHANGE link is clicked, the controls
count now comes to 3. Why?

This is really drving me crazy!

Arpan
 

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

Controls In DataGrid? 1
Controls 2
Controls 3
DataGrid Edit Problem 9
Dynamic BoundColumn 2
DropDownList DataGrid 1
Cells.Controls 0
DataBind In ItemDataBound Event 1

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top