Programmatically Add ButtonColumn to GridView From DataTable - asp.net

I have a problem adding a column with buttons in GridView.
As you see from the code below, the data source from teh GridView is a DataTable. I need to add an additional column to the table with a button.
From the code below, I get an error message saying:
Value of type 'System.Windows.Forms.DataGridViewButtonColumn' cannot
be converted to 'System.Web.UI.WebControls.DataControlField'.
Dim dt_AllGroupsSetUp2 As New DataTable()
dt_AllGroupsSetUp2.Columns.Add("Name", Type.GetType("System.String"))
dt_AllGroupsSetUp2.Columns.Add("Age", Type.GetType("System.String"))
dt_AllGroupsSetUp2.Columns.Add("Hight", Type.GetType("System.String"))
For i As Integer = 0 To 7
dt_AllGroupsSetUp2.Rows.Add()
dt_AllGroupsSetUp2.Rows(i)(0) = "John"
dt_AllGroupsSetUp2.Rows(i)(1) = 10
dt_AllGroupsSetUp2.Rows(i)(2) = 70
Next
GV_DataByGroupAct.DataSource = dt_AllGroupsSetUp2
Dim buttonColumn As New DataGridViewButtonColumn
buttonColumn.Name = "Button"
GV_DataByGroupAct.Columns.Add(buttonColumn)
GV_DataByGroupAct.DataBind()
I tried the folling also but returned the following error: 'New' cannot be used on a class that is declared 'MustInherit'.
GV_DataByGroupAct.DataSource = dt_AllGroupsSetUp2
Dim buttonColumn As New DataControlField
GV_DataByGroupAct.Columns.Add(buttonColumn)
GV_DataByGroupAct.DataBind()
Any ideas?
Thanks

In the code behind use this before binding data to GridView (but it's c#):
GV_DataByGroupAct.Columns.Add(new ButtonField() { Text = "Button" });
Or you could prepare the GridView with the button field
<asp:GridView ID="GV_DataByGroupAct" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="Age" HeaderText="Age" />
<asp:BoundField DataField="Hight" HeaderText="Hight" />
<asp:ButtonField Text="Button" />
</Columns>
</asp:GridView>
after bind you will have this result:

I was really complicating things. Thanks Jenda, it is easier to prepare the grid view. The following workds if it helps someone:
<asp:GridView ID="GV_DataByGroupAct" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="Age" HeaderText="Age" />
<asp:BoundField DataField="Hight" HeaderText="Hight" />
<asp:ButtonField Text="Button" />
</Columns>
</asp:GridView>
Code:
Dim dt_AllGroupsSetUp2 As New DataTable()
dt_AllGroupsSetUp2.Columns.Add("Name", Type.GetType("System.String"))
dt_AllGroupsSetUp2.Columns.Add("Age", Type.GetType("System.String"))
dt_AllGroupsSetUp2.Columns.Add("Hight", Type.GetType("System.String"))
For i As Integer = 0 To 7
dt_AllGroupsSetUp2.Rows.Add()
dt_AllGroupsSetUp2.Rows(i)(0) = "John"
dt_AllGroupsSetUp2.Rows(i)(1) = 10
dt_AllGroupsSetUp2.Rows(i)(2) = 70
Next
GV_DataByGroupAct.DataSource = dt_AllGroupsSetUp2
GV_DataByGroupAct.DataBind()

DataGridViewButtonColumn is intended to be used in DataGridView control.
With GridView you can use ButtonField.

Related

How do I make a read only cell editable in a gridview control in asp using vb?

Hi me again with another question.
I'm using VS2019 and VB on an aspx page. I have a gridview that has Edit enabled.
enter image description here
When a user clicks the EDIT link Progress % and Comments become editable.
What I want to do is make the Goal be editable if Approved is set to No.
How can I do this?
<asp:GridView ID="grdgoals" runat="server" AutoGenerateColumns="False" DataSourceID="DS1" Height="225px" Width="1001px" BorderColor="#003960" BorderStyle="Solid" BorderWidth="1px" DataKeyNames="goalid" EmptyDataText="No goals found." Font-Bold="True" Font-Names="Calibri" Font-Overline="False" Font-Size="Medium" Font-Strikeout="False" ForeColor="#00AD86" ShowHeaderWhenEmpty="True" AllowSorting="True" style="margin-right: 21px">
<Columns>
<asp:BoundField DataField="goalid" HeaderText="goalid" ReadOnly="True" SortExpression="goalid" Visible="False" />
<asp:CommandField EditText="EDIT" ShowEditButton="True" ShowHeader="True">
<HeaderStyle BorderColor="#003960" />
<ItemStyle Font-Names="Calibri" Font-Underline="True" ForeColor="#006EAA" HorizontalAlign="Center" BorderColor="#003960" Width="20px" />
</asp:CommandField>
<asp:BoundField DataField="goaltext" HeaderText="Goal" SortExpression="goaltext" ReadOnly="True" >
<HeaderStyle BorderColor="#003960" />
<ItemStyle BorderColor="#003960" Width="250px" />
</asp:BoundField>
<asp:BoundField ConvertEmptyStringToNull="True" DataField="type" HeaderText="Type" ReadOnly="True" >
<ItemStyle Width="70px" />
</asp:BoundField>
<asp:BoundField DataField="progress" HeaderText="Progress %" SortExpression="progress" >
<HeaderStyle BorderColor="#003960" />
<ItemStyle HorizontalAlign="Center" BorderColor="#003960" VerticalAlign="Middle" Width="20px" />
</asp:BoundField>
<asp:BoundField DataField="comments" HeaderText="Comments" SortExpression="comments" ItemStyle-Wrap="true">
<ControlStyle Height="400px" Width="240px" />
<HeaderStyle BorderColor="#003960" />
<ItemStyle BorderColor="#003960" Width="250px" HorizontalAlign="Left" VerticalAlign="Middle" />
</asp:BoundField>
<asp:BoundField DataField="approved" HeaderText="Approved" ReadOnly="True" SortExpression="approved" >
<ItemStyle HorizontalAlign="Center" Width="40px" />
</asp:BoundField>
</Columns>
<EditRowStyle HorizontalAlign="Left" VerticalAlign="Top" />
<HeaderStyle ForeColor="#006EAA" />
</asp:GridView>
I have searched online looking for answer but haven't found anything.
Ok, so how much extra code is it to simple drop in a "plain jane" button to click on and edit?
It not much!!!
You do have to bear the cost/time of building a form layout for the one row, but at the end of the day:
this tends to be "easy" for the users.
You can also then move the row delete button to that "form layout" area for editing one record. (this means you don't need a delete record button on the GV - not a huge deal, but that means users have to make a "bit more" effort to delete a row of data if that option is desired).
However, the "why" of having a detail edit layout?
You can now have MUCH more control over your logic (such as the rule to allow what to edit, change or even "enable" based on other values. And such code is clean easy server side code.
And this allows far more code logic into the editing of that data. (required fields, formatting, all that stuff.
Best bonus feature?
Such a approach now ALSO allows adding of new records in a MUCH more user friendly way, since now the "edit" area you build ALSO can be used as the "add new" record area. (so, you save having to write separate code for edit and adding - the one solution does both). And this also means the end user has the "same" experience when editing existing, or adding new - it shortens the user learning curve.
Now, about the only downside?
Well, when starting out, those wizards can be a real gift horse. And I still after all these years often use the wizard(s) to create the GV.
however, I THEN clean it up a bit, and remove things from the page.
(such as removing the datasource on the page).
And the other tip?
If possbile, build a few "helper" routines. They can be used over and over.
For example, I became VERY tired of having to type in code with a row of data, and then "please fill out" those controls on the page with that data.
Then after done, we have to take that those controls, and send back to the database. We do this "over and over". And the code to do this is darn near the "same" over and over. So, then, why not write one sub routine that can do this for ANY page we work on!!!
So, here is a working approach.
for the GV, then the markup becomes rather clean - just some fields.
Say, like this markup:
<asp:GridView ID="GridView1" runat="server" Width="40%"
AutoGenerateColumns="False" DataKeyNames="ID"
CssClass="table table-hover table-striped" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn myshadow"
OnClick="cmdEdit_Click"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note a few things in above:
If we don't use width, or use 100%? The GV will expand to the WHOLE page - it is what we call "responsive".
I assume that you have bootstrap installed, and most projects do (by default).
The result is a "very" nice grid, and the fonts + spacing and layout is "tweaked" by bootstrap. The result is quite nice.
Code to load the GV is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
End Sub
Sub LoadData()
Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
Dim cmdSQL As New SqlCommand(strSQL)
GridView1.DataSource = MyrstP(cmdSQL)
GridView1.DataBind()
End Sub
Note the "helper" routine MyrstP. I use this "over and over" everywhere.
(I'll post that at end of this post).
So, I removed the Sqldatasourc1 from the page. I find that you obtain/enjoy MUCH more control over the code. (but, if you don't have a helper routine, then setting up a query + connection and all that jazz? Then you might as well just stick with the wizard generated SqlDataSource on the page. But, you find over time that using code behind is a "less effort" choice, and one that gives you far more control (say to filter, or do other things).
And note the table hover (you get a "nice" row hover effect), and note the table-striped. That gives you a nice alternating row shade - and you do not need a messy "alternating" template.
So far? We have a VERY clean markup, and so far VERY little code has been written.
Now, not the button we dropped into the GV. That is a plan jane asp.net button. We don't need to use "speical" commands, "speical" code or anything. Just a good old fashioned button and button click.
However, do note that we have a click event for the button. Normally, I often just double click on a button, and then a code behind stub is created, and we are jumped to the code behind editor.
however, since the button is "nested" in a GV, then we can't double click on that button to create a event.
So, flip to markup. And in markup type in
OnClick=
WHEN you hit the "=", then intel-sense should pop up and gives you the option to create the event. (since we can't use double click on button to do this).
So, it looks like this:
And thus the code is for button click:
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
Dim cmdSQL = New SqlCommand("SELECT * FROM tblHotelsA WHERE ID = #ID")
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = intPK
Dim rstHotel As DataTable = MyrstP(cmdSQL)
ViewState("PKID") = intPK
fLoader(EditRecord, rstHotel.Rows(0))
GridView1.Visible = False ' Hide GV
EditRecord.Visible = True ' show edit area
End Sub
Again, note the small amount of code.
The button click thus:
we get GV row
we get GV row PK database ID (using datakeys feature)
we pull that data row into data table
we call the floader() routine that takes ONE row, fills out controls.
the resulting effect is thus this:
And our helper MyRstP routine is this:
Public Function MyrstP(cmdSQL As SqlCommand,
Optional cmdOnly As Boolean = False) As DataTable
Dim rstData As New DataTable
Using mycon As New SqlConnection(GetConstr)
Using (cmdSQL)
cmdSQL.Connection = mycon
mycon.Open()
If cmdOnly Then
cmdSQL.ExecuteNonQuery()
Else
rstData.Load(cmdSQL.ExecuteReader)
End If
End Using
End Using
Return rstData
End Function
I'll post more code from above (later this evening)., and say have some "conditional" code. Say if the hotel not active, we can't edit description.

.NET - SelectedRow not returning any value

I am new with .net!
I have two gridviews connected to a large database. The first one is returning a list of issues searched by ID while the other is returning the issues searched by subject.
I am trying to get the ID from the gridview returning issues from a select button but when I use selectedRow it doesn't return anything.
I tried multiple methods and this is what I have now. Any Suggestions?
Protected Sub IssuesGV_SelectedIndexChanging(ByVal sender As Object, ByVal e As GridViewSelectEventArgs)
Dim pName As String
pName = IssuesGV.SelectedRow.Cells(0).Text
BindGridComments(pName)
End Sub
Protected Sub IssuesGV_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes("onmouseover") = "this.style.backgroundColor='aquamarine';"
e.Row.Attributes("onmouseout") = "this.style.backgroundColor='white';"
e.Row.ToolTip = "Click last column for selecting this row."
' e.Row.Cells(0).Attributes.Add("onclick", )
End If
End Sub
Protected Sub IssuesGV_RowCommand(sender As Object, e As GridViewCommandEventArgs)
' ' Dim row As GridViewRow = IssuesGV.Rows(rowIndex)
' v = row.Cells(1).Text
'v = IssuesGV.SelectedRow.Cells(0).Text
' TextBox1.Text = v
'TextBox1.Text = v
If (e.CommandName = "Select1") Then
Dim index As Int16
index = Convert.ToInt32(e.CommandArgument)
Dim row As GridViewRow
row = IssuesGV.Rows(index)
Dim item As ListItem
item.Text = Server.HtmlDecode(row.Cells(0).Text)
End If
End Sub
My gridview code is the following (the one where I am using the select button):
<asp:GridView ID="IssuesGV" runat="server" AutoPostBack="true" OnRowCommand ="IssuesGV_RowCommand" OnRowDataBound="IssuesGV_RowDataBound" OnSelectedIndexChanged = "IssuesGV_OnSelectedIndexChanged" SelectedIndexChaning ="IssuesGV_SelectedIndexChanging" AutoGenerateColumns="False" DataKeyNames="number" DataSourceID="IssueDS" EnableModelValidation="True">
<Columns>
<asp:BoundField DataField="number" HeaderText="number" ReadOnly="True" SortExpression="number" />
<asp:BoundField DataField="subject" HeaderText="subject" SortExpression="subject" />
<asp:BoundField DataField="description" HeaderText="description" SortExpression="description" />
<asp:BoundField DataField="created_at" HeaderText="created_at" SortExpression="created_at" />
<asp:BoundField DataField="opener_name" HeaderText="opener_name" SortExpression="opener_name" />
<asp:BoundField DataField="project_name" HeaderText="project_name" SortExpression="project_name" />
<asp:ButtonField Text="Select" CommandName="Select1" ItemStyle-Width="30" ButtonType="Button" HeaderText="Select" ShowHeader="True" SortExpression="number" >
<ItemStyle Width="30px" />
</asp:ButtonField>
</Columns>
</asp:GridView>
The error I am receiving is this one:
System.ArgumentOutOfRangeException HResult=0x80131502
Message=Index was out of range. Must be non-negative and less than the
size of the collection. Parameter name: index Source= StackTrace:
Many Thanks!
Front End:
Your GridView should look like this:
<asp:GridView ID="IssuesGV" runat="server" AutoGenerateColumns="false"
OnSelectedIndexChanged="IssuesGV_OnSelectedIndexChanged">
<Columns>
<asp:BoundField DataField="number" HeaderText="number" />
...Some Other Fields
<asp:ButtonField Text="Select" CommandName="Select" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
Back End:
Then add this code OnSelectedIndexChanged of GridView:
Protected Sub IssuesGV_OnSelectedIndexChanged(sender As Object, e As EventArgs)
'Accessing Selected BoundField Column
Dim number As String = IssuesGV.SelectedRow.Cells(0).Text
label.Text = "<b>Number Value:</b> " & number & " <b>"
End Sub
Ref: See full example here.
Edit
For some reason, if OnSelectedIndexChanged method is not firing then you've just need to add below attribute in your GridView header markup:
AutoGenerateSelectButton="True"
This will create a Select link in your GridView rows, which'll fire the OnSelectedIndexChanged method.
PS: If above all workarounds not works then see this post.

Gridview not sorting

I've come across this strange error and it's been bugging me for hours now.
I've got some LinkButtons on my screen and depending on which button the user chooses a label's text is set, a GridView is displayed and the Datasource of this GridView is assigned based on the text of the label.
This all works fine and dandy. However the problem arises when I want to sort this GridView.
At the moment, nothing happens. When I attempt to sort a column the page just refreshes and I'm left with the same unsorted mess in my GridView.
I've put my application into debug mode with breakpoints along the way and noticed that when I get to this step (the full code can be seen at the bottom of this post) :
senderGridView.SortExpression = button.CommandArgument
the senderGridView.SortExpression is "" so for some reason it's not passing the sort expression.
Hopefully somebody can enlighten me as to why my grid isn't sorting as I'm sure it's just a stupid mistake somewhere but any help would be appreciated, thanks.
Code that you may require...
My sub that sets the sort images when a row is created can be seen below:
Protected Sub GridViewSortImages(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
Dim senderGridView As GridView = CType(sender, GridView)
'Loop through each cell in header row
For Each cell As TableCell In e.Row.Cells
If cell.HasControls Then
Dim button As LinkButton = TryCast((cell.Controls(0)), LinkButton)
Dim gv As New HtmlGenericControl("div")
Dim lnkName As New Label()
'Test cell to see if a link button exists (i.e. Allow Sorting = True)
If Not (button Is Nothing) Then
'Create new label and image and set to standard unsorted view
lnkName.Text = button.Text
Dim image As New System.Web.UI.WebControls.Image
image.ImageUrl = "images/sort-1x1.png"
image.ToolTip = "Sort"
image.AlternateText = "Sort"
'Test to see if grid is already sorted, and apply relevant image & tooltip
If senderGridView.SortExpression = button.CommandArgument Then
If senderGridView.SortDirection = SortDirection.Ascending Then
image.ImageUrl = "images/sort-asc.png"
image.ToolTip = "Sort Descending"
image.AlternateText = "Sort Descending"
Else
image.ImageUrl = "images/sort-desc.png"
image.ToolTip = "Sort Ascending"
image.AlternateText = "Sort Ascending"
End If
End If
'Add label and image to new div
gv.Controls.Add(lnkName)
gv.Controls.Add(image)
'Replace original column header with new div
button.Controls.Add(gv)
End If
End If
Next
End Sub
My RowCreated sub for the GridView...
Protected Sub grvHomeRisk_RowCreated(sender As Object, e As GridViewRowEventArgs) Handles grvHomeRisk.RowCreated
If Not (e.Row Is Nothing) AndAlso e.Row.RowType = DataControlRowType.Header Then
GridViewSortImages(sender, e) 'Call sort code
End If
End Sub
My Sorting sub...
Protected Sub grvHomeRisk_Sorting(sender As Object, e As GridViewSortEventArgs) Handles grvHomeRisk.Sorting
Select Case lblBreachHeaderb.Text
Case "Current Risks"
grvHomeRisk.DataSource = SQLDS_ListCurrentRisk
Case "All Risks Overdue"
grvHomeRisk.DataSource = SQLDS_ListAllRiskOverdue
Case "My Risks"
grvHomeRisk.DataSource = SQLDS_ListMyRisk
Case "My Risks Overdue"
grvHomeRisk.DataSource = SQLDS_ListRiskOverdue
Case "Risks Requested to Score & Re-Score"
grvHomeRisk.DataSource = SQLDS_ListScores
Case "Risks Requested to Score"
grvHomeRisk.DataSource = SQLDS_ListRiskScores
Case "Risks Requested to Re-Score"
grvHomeRisk.DataSource = SQLDS_ListRiskReScores
End Select
grvHomeRisk.DataBind()
End Sub
My GridView...
<asp:GridView ID="grvHomeRisk" runat="server" AutoGenerateColumns="false" AllowSorting="true"
CssClass="GridMain" UseAccessibleHeader="false"
ForeColor="#333333" GridLines="None" Width="780px" BorderWidth="0px"
AllowPaging="true" PageSize="5" CellPadding="3" DataKeyNames="IDRISK">
<Columns>
<asp:CommandField ButtonType="Image" SelectText="View Risk" ShowSelectButton="True" SelectImageUrl="~/Images/button-select1.png" />
<asp:BoundField DataField="TXRISKSUMMARY" HeaderText="Risk" ReadOnly="True" />
<asp:BoundField DataField="TSRISKSTART" HeaderText="Start Date" ReadOnly="True" DataFormatString="{0:dd MMM yyyy}" />
<asp:BoundField DataField="TSRISKREVIEW" HeaderText="Review Date" SortExpression="TSRISKREVIEW" ReadOnly="True" DataFormatString="{0:dd MMM yyyy}" />
<asp:BoundField DataField="TXUSER_NAME_O" HeaderText="Owner" SortExpression="TXUSER_NAME_O" ReadOnly="True" />
<asp:BoundField DataField="TXDESCRIPTION" HeaderText="Risk Element" SortExpression="TXDESCRIPTION" ReadOnly="True" />
<asp:BoundField DataField="TSDATMOD" HeaderText="Date Modified" ReadOnly="True" DataFormatString="{0:dd MMM yyyy}" />
<asp:BoundField DataField="TXUSER_NAME_M" HeaderText="Modified By" ReadOnly="True" />
</Columns>
<PagerTemplate>
<table>
<tr>
<td>
<asp:Button ID="FirstButton" runat="server" CommandArgument="First" CommandName="Page" Text="<<" CssClass="buttongrid" ToolTip="First" OnClientClick="needToConfirm = false;" />
<asp:Button ID="PrevButton" runat="server" CommandArgument="Prev" CommandName="Page" Text="Previous" CssClass="button" ToolTip="Previous" OnClientClick="needToConfirm = false;" />
</td>
<td>
<asp:Label ID="lblPageCount" runat="server" CssClass="TextA12Bold" Visible="false"></asp:Label>
</td>
<td>
<asp:Button ID="NextButton" runat="server" CommandArgument="Next" CommandName="Page" Text="Next" CssClass="button" ToolTip="Next" OnClientClick="needToConfirm = false;" />
<asp:Button ID="LastButton" runat="server" CommandArgument="Last" CommandName="Page" Text=">>" CssClass="buttongrid" ToolTip="Last" OnClientClick="needToConfirm = false;" />
</td>
</tr>
</table>
</PagerTemplate>
</asp:GridView>

Calling Data From GridView

I have a GridView with a bunch of DynamicFields like so;
<asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource">
<Columns>
<asp:DynamicField HeaderText="Date Submitted" DataField="DATE_CREATED" />
<asp:DynamicField HeaderText="Assigned To" DataField="ASSIGNED_TO" />
<asp:DynamicField HeaderText="Active Account" DataField="Active_Account" />
<asp:DynamicField HeaderText="Client ID" DataField="CLIENT_ID" />
<asp:DynamicField HeaderText="Client Type" DataField="CLIENT_Type" />
</Columns>
</asp:GridView>
<asp:EntityDataSource ID="GridDataSource" OnSelected="TotalRows" runat="server"
EnableDelete="true">
<WhereParameters>
<asp:DynamicControlParameter ControlID="FilterRepeater" />
</WhereParameters>
</asp:EntityDataSource>
Now it displays fine, the right data comes to screen but when I try to access that data using a row number I'm always finding blank cells. For example I tried the following to check every cell but to no avail;
Dim x As Integer = 0
Dim y As Integer = 0
While x < GridView1.Rows.Count
While y < GridView1.Rows(x).Cells.Count
If Not (GridView1.Rows(x).Cells(y).Text = "") Then
MsgBox(String.Format("{0},{1},{2}", x.ToString, y.ToString,
GridView1.Rows(x).Cells(y).Text))
End If
y = y + 1
End While
x = x + 1
y = 0
End While
No message box displayed so all the cells are empty strings. But I can clearly see they're populated on screen! What am I doing wrong?
UPDATE
After Pilgerstorfer Franz suggestion that I look for Textbox elements I used the following code which basically looks at all the cells in the table and try's to pull data out of them and if it's not blank then display a msgbox (also informs me of any new controls I haven't accounted for);
If GridView1.Rows(0).RowType = DataControlRowType.DataRow Then
For r = 0 To GridView1.Rows.Count - 1
For c = 0 To (GridView1.Rows(r).Cells.Count - 1)
Dim cell = GridView1.Rows(r).Cells(c)
For b = 0 To cell.Controls.Count - 1
If (cell.Controls(b).GetType() Is GetType(TextBox)) Then
Dim td = CType(cell.Controls(b), TextBox)
Text = td.Text.Trim
ElseIf (cell.Controls(b).GetType() Is GetType(LiteralControl)) Then
Dim td = CType(cell.Controls(b), LiteralControl)
Text = td.Text.Trim
ElseIf (cell.Controls(b).GetType() Is GetType(DynamicControl)) Then
Dim td = CType(cell.Controls(b), DynamicControl)
Text = td.Table.Columns.Item(c).DisplayName()
Else
MsgBox(String.Format("New Control of type: {0}", cell.Controls(b).GetType().FullName))
End If
If Not Text = "" Then
MsgBox(String.Format("{0},{1},{2}", c.ToString, b.ToString, Text))
End If
Next
Next
Next
End If
Unfortunately most cells just contained DynamicControl and since I was putting the DisplayName into Text I was just getting the column header every time. So how do I get the text value property out of a DynamicControl?
Additional Info
I'm further confused by this problem because since this is a project that I'm updating there is initial code two lines of which are;
Dim UserID = Convert.ToInt32(GridView1.DataKeys(e.RowIndex).Value)
Dim clientType As String = GridView1.DataKeys(e.RowIndex).Item(1).ToString
These successfully bring back UserID and ClientType. Now I don't really understand DataKeys but I tried using;
Dim clientType As String = GridView1.DataKeys(e.RowIndex).Item(Num).ToString
where Num increases by one every time expecting it to bring back the rest of the row data, but I simply got an index was out of range error.
ANOTHER UPDATE!!
Here is another bit of the ASPX page but I'n not entirely certain what it does. Pilgerstorfer Franz created some code to look for the textboxes created by the dynamicControl. Now I'm wondering if this code here causes other types of controls to be used rather than Textboxes. Thoughts?
<asp:FilterRepeater ID="FilterRepeater" runat="server" Visible="false">
<ItemTemplate>
<h2><asp:Label ID="lblDisplay" runat="server" Text='<%#
Eval("DisplayName") %>' AssociatedControlID="DynamicFilter$DropDownList1" /></h2>
<asp:DynamicFilter runat="server" ID="DynamicFilter"
OnSelectedIndexChanged="OnFilterSelectedIndexChanged" />
</ItemTemplate>
<FooterTemplate><br /><br /></FooterTemplate>
</asp:FilterRepeater>
According to my assumptions (see comments) I did a small demo...
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server">
<DataControls>
<asp:DataControlReference ControlID="GridView1" />
</DataControls>
</asp:DynamicDataManager>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ContactID" DataSourceID="EntityDataSource1" AllowPaging="true"
OnRowUpdating="GridView1_RowUpdating">
<Columns>
<asp:DynamicField DataField="ContactID" ReadOnly="true" HeaderText="ContactID" />
<asp:DynamicField DataField="Title" HeaderText="Title" />
<asp:DynamicField DataField="FirstName" HeaderText="FirstName" />
<asp:DynamicField DataField="LastName" HeaderText="LastName" />
<asp:CommandField ShowEditButton="True" />
</Columns>
</asp:GridView>
<asp:EntityDataSource ID="EntityDataSource1" runat="server" ConnectionString="name=dbTestIT34_EFEntities"
DefaultContainerName="dbTestIT34_EFEntities" EnableFlattening="False" EnableUpdate="True"
EntitySetName="Contacts" EntityTypeFilter="Contact">
</asp:EntityDataSource>
And according to my data storage I did handle the rowUpdating event. Unfortunatelly accessing any control within a dynamic control is not easy. So I did a very quick and dirty hack...
protected void Page_Init(object sender, EventArgs e)
{
GridView1.EnableDynamicData(typeof(Contact));
EntityDataSource1.ContextType = typeof(dbTestIT34_EFEntities);
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int row = 0;
int firstNameColumn = 2;
while (row < GridView1.Rows.Count)
{
// sorry, a little bit confusing ...
// as dynamic control generates other controls dynamically,
// this was the very first thing that worked for me!
TextBox t = GridView1.Rows[row].Cells[firstNameColumn].Controls[0].Controls[0].Controls[0] as TextBox;
if (t != null)
Debug.WriteLine(t.Text);
row++;
}
}
Hope that helps!
Iterating through the controls never worked for me so in the end I gave up and just queried the DB again... Eh it works.

How to get the non visible gridview cell value in ASP.net?

I have a grid like below.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" s
onrowcommand="GridView1_RowCommand">
<Columns>
<asp:ButtonField DataTextField="Name" HeaderText="Name" />
<asp:BoundField DataField="ArrDate" DataFormatString="{0:MM/dd/yyyy}"
HeaderText="Arr Date" />
<asp:BoundField HeaderText="Dep Date" DataField="DepDate"
DataFormatString="{0:MM/dd/yyyy}" />
<asp:BoundField HeaderText="Mail" DataField="Mail" />
<asp:BoundField HeaderText="Status" DataField="Status" />
<asp:BoundField DataField="ResId" HeaderText="ResId" Visible="False" />
</Columns>
</asp:GridView>
In Code Behind:-
try
{
string text = GridView1.Rows[2].Cells[5].Text;
ScriptManager.RegisterStartupScript(this, GetType(), "Message", "alert('ResId = " + text + ".');", true);
}
catch { }
Now the message shows - RegId =.
I can't get the value. So I change the RedId BoundField as vissible. Now I got the Value.
that is RegId =6.
I have two issue now -
1) How to get the RegId value in Non Visible Column.
2) How I find the Row value which i click... bzs the only i can change the ROWVALUE in code..
string text = GridView1.Rows[ROWVALUE].Cells[5].Text;
That is certainly not the right way to do it. You might want to look at using DataKeys to achieve this. With current approach, when you add a new column to your grid your code will fail.
Add your RegId column inside DataKeys property on your gridview
Reference your gridview datakey for the current row in codebehind like this
int regId= Convert.ToInt32(YourGridview.DataKeys[rowIndex]["RegId"].ToString());

Resources