ASP.NET - Accessing a Repeater nested in a GridView column? - asp.net

I have a blank Repeater nested inside a column in a GridView and want to use a button in the GridView to populate the Repeater on demand via code behind. I am having difficulties referencing the repeater inside my button's onCommand sub.
Here is the relevant markup:
<asp:GridView ID="Submission" runat="server" AllowPaging="true" AllowSorting="true" />
<Columns>
..........
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:ImageButton ID="AdminEditSubmission" runat="server" ImageUrl="edit_15.png"
alt="" OnCommand="loadDetails" CommandArgument="X" />
</ItemTemplate>
</asp:TemplateField>
..........
<asp:TemplateField>
<ItemTemplate>
<asp:Repeater ID="RptSubmissionDetail" runat="server">
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
For the sake of this small example, I will simply try to update the repeater's header with "Hello world". However, when it gets to the last line, I get the dreaded "Object reference not set to an instance of an object" error.
Sub loadDetails(sender As Object, e As CommandEventArgs)
Dim rpt As Repeater = CType(Page.FindControl("RptsSubmissionDetail"), Repeater)
Dim tmpHdr As TemplateBuilder = New TemplateBuilder
tmpHdr.AppendLiteralString("Hello World")
rpt.HeaderTemplate = tmpHdr
End Sub
Can anyone tell me how to reference this repeater from my ImageButton click sub? I have tried several, with Page.FindControl("RptsSubmissionDetail") only being my latest attempt.

In GridView's RowCommand you need to use FindControl on the GridViewRow:
Sub Submission_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
If e.CommandName = "loadDetails" Then
' Convert the row index stored in the CommandArgument
' property to an Integer.
Dim index = Convert.ToInt32(e.CommandArgument)
' Retrieve the row that contains the button clicked
' by the user from the Rows collection.
Dim row = Submission.Rows(index)
Dim repeater = DirectCast(row.FindControl("RptSubmissionDetail"), Repeater)
End If
End Sub
From the ImageButton's click event it's nearly the same. Cast the sender argument to the ImageButton and it's NamingContainer property to the GridViewRow. Then use FindControl as shown above:
Sub ImageButton_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim img = DirectCast(sender, ImageButton)
Dim row = DirectCast(img.NamingContainer, GridViewRow)
Dim repeater = DirectCast(row.FindControl("RptSubmissionDetail"), Repeater)
End Sub

In your ImageButton Click event write the following code
For Each row As GridViewRow In Submission.Rows
Dim r As Repeater = DirectCast(row.FindControl("RptsSubmissionDetail"), Repeater)
If r IsNot Nothing Then
' do your work
End If
Next
or if you want to find repearter in a particular row you can find it as
Dim r As Repeater = DirectCast(Submission.Rows[0].FindControl("RptsSubmissionDetail"), Repeater) ' Give the right index
If r IsNot Nothing Then
' do your work
End If

Related

Asp:Repeater Datasouce - Datatable Checkbox inside Repeater. Delete the current row

Couldn't find anything like it.
The page has a Repeater, the data source is a datatable. Rows from the page are added to the datatable, then Repeater is updated and displayed on the page. For example, a user has added incorrect information and needs to remove something from Repeater by placing a check mark in the Checkbox. If the Checkbox is checked, the selected data (a row in the datatable ) should be removed from the data source and Repeater should be updated. How can this be implemented and whether it is possible at all? My code:
<asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:TableCell Width="80px" BackColor="#e3a99a" HorizontalAlign="Right">
<asp:CheckBox ID="cb_GetOut" runat="server" AutoPostBack="true" Checked="false" Text="DeleteRow" style="padding-right:5px" />
</asp:TableCell>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack = False Then
dtTest_add.Columns.AddRange(New DataColumn(3) {New DataColumn("text1"), New DataColumn("text2"), New DataColumn("text3"), New DataColumn("text4")})
ViewState("dtTest_add") = dtTest_add
Else
dtTest_add = ViewState("dtTest_add")
Repeater1.DataSource = TryCast(ViewState("dtTest_add"), DataTable)
Repeater1.DataBind()
End If
End Sub
Protected Sub btn_addTest_Click(sender As Object, e As System.EventArgs) Handles btn_addTest.Click
dtTest_add.Rows.Add(txt1.Text, txt2.Text, txt3.Text, txt4.Text)
dtTest_add = ViewState("dtTest_add")
ViewState("dtTest_add") = dtTest_add
Repeater1.DataSource = TryCast(ViewState("dtTest_add"), DataTable)
Repeater1.DataBind()
UpdatePanel1.Update()
End Sub
Protected Sub Repeater1_ItemCreated(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemCreated
Dim cb_GO As CheckBox = CType(e.Item.FindControl("cb_GetOut"), CheckBox)
ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(cb_GO)
End Sub
Protected Sub Repeater1_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim cb_GO As CheckBox = DirectCast(e.Item.FindControl("cb_GetOut"), CheckBox)
cb_GO.Attributes("onclick") = "this.checked = (" + dtTest_add + ").deleteRow(" + CStr(e.Item.ItemIndex) + ");"
End Sub
The "btn_addTest" button is on a form not in Repeater. With it I add data to the data source. Then update the Repeater.
I handle the "onclick" Checkbox event in this line of code
cb_GO.Attributes("onclick") = "this.checked = (" + dtTest_add +
").deleteRow(" + CStr(e.Item.ItemIndex) + ");"
It is necessary to remove data from datatable, and Repeater will simply be updated then and all. But how do you do that? Can't get through to a datatable with the Repeater in ItemDataBound.

How to pass the value to the dropdown list to be highlighted value on Edit template?

The label lblTempLib in the Form has the data coming from table A. This needs to be passed on to the dropdown list as the selected value to datasource in the edit template.
This is the object datasource for LibDS (markup):
SelectCommand="SELECT [LibName] FROM [tblBuilding]"></asp:SqlDataSource>
<asp:FormView ID="frmUpdateIncident" runat="server" DataSourceID="InciDetailDS" OnDataBound="frmUpdateIncident_DataBound">
<EditItemTemplate>
<asp:Label runat="server" ID="lblLib" Text="Library:" CssClass="style_bold"></asp:Label><br />
<asp:Label ID="lblTempLib" runat="server" Text='<%# Eval("Library")%>'Visible="true"></asp:Label>
<asp:Dropdownlist runat="server" ID="ddLib" DataTextField="LibName" DataSourceID="LibDS" >
</asp:Dropdownlist>
VB.NET code:
Protected Sub frmUpdateIncident_DataBound(sender As Object, e As EventArgs) Handles frmUpdateIncident.DataBound
Dim ddLib As DropDownList
Try
If Page.FindControl("ddLibrary") IsNot Nothing Then
ddLib = DirectCast(frmUpdateIncident.FindControl("ddLibrary"), DropDownList)
ddLib.Items.FindByText(strLibName).Selected = True
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Ok, I finally got it. Need to pass the index value to the dropdown SelectedIndex value as this property can get and set the value unlike SelectedValue.
strLibName is the value passed on by the previous form.
I hardcoded ddLib.SelectedIndex in here to test it but I will be fixing it by passing the list index value.
VB.Net Code:
Protected Sub frmUpdateIncident_DataBound(sender As Object, e As EventArgs) Handles frmUpdateIncident.DataBound
If frmUpdateIncident.CurrentMode = FormViewMode.Edit Then
Dim ddlib As DropDownList
ddlib = DirectCast(frmUpdateIncident.FindControl("ddLibrary"), DropDownList)
If ddLib IsNot Nothing Then
If ddLib.Items.Count > 0 Then
If strLibName IsNot Nothing Then
ddlib.SelectedIndex = 2
Dim strtest As String = ddlib.SelectedValue.Trim
End If
End If
End If
End If
End Sub

Find the right value of textbox

I have a problem with inserting data inserting data into database.
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<!-- Some other data (text...) -->
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Eval("PostId") %>' />
<asp:TextBox ID="txtAddComment" runat="server" CssClass="textbox" Width="200px" />
<asp:Button ID="btnAddComment" runat="server" CssClass="button" Text="Comment" CausesValidation="false" OnClick="btnAddComment_Click"/>
</ItemTemplate>
</asp:Repeater>
Code behind:
Protected Sub btnAddComment_Click(sender As Object, e As EventArgs)
Dim HiddenField1 As HiddenField = DirectCast(Repeater1.Items(0).FindControl("HiddenField1"), HiddenField)
Dim txtAddComment As TextBox = DirectCast(Repeater1.Items(0).FindControl("txtAddComment"), TextBox)
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString.ToString)
Try
If txtAddComment.Text = "" Then
Exit Sub
Else
conn.Open()
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "INSERT INTO Comments (PostId, UserName, CommentText) VALUES (#PostId, #UserName, #Text)"
cmd.Parameters.Add("PostId", System.Data.SqlDbType.Int).Value = CInt(HiddenField1.Value)
cmd.Parameters.Add("UserName", System.Data.SqlDbType.NVarChar).Value = Context.User.Identity.Name
cmd.Parameters.Add("Text", System.Data.SqlDbType.NText).Value = MakeLink(HtmlRemoval.StripTagsCharArray(txtAddComment.Text))
cmd.ExecuteNonQuery()
End If
Catch ex As SqlException
Finally
conn.Close()
End Try
End Sub
I display some text, under the text there is textbox and button for comments. I am bounding textId in hiddenfield for inserting comments. The code works fine, but I can only add comment for the first row in database displayed by repeater. When I want to add comment for other rows (2, 3...), the page refreshes and the text in the TextBox stay there.
It is problem with this line of code:
Dim txtAddComment As TextBox = DirectCast(Repeater1.Items(0).FindControl("txtAddComment"), TextBox)
The ID from HiddenField is right. But the code doesn't perform because the line above references for the first textbox on the page and his value is null.
When I change the line of code like this:
Dim txtAddComment As TextBox = DirectCast(Repeater1.FindControl("txtAddComment"), TextBox)
It returns an error that Object reference not set to an instance of an object.
How to get the right textbox with right value?
Thanks for the answer
cast the sender to a button that sent it, then get the textbox from the parent. Example:
Protected Sub button_click(ByVal sender As Object, ByVal e As EventArgs)
Dim myButton As button= CType(sender, button)
Dim myTextBox as TextBox = CType(myButton Parent.FindControl("buttonName"), TextBox)
end sub

how to get value of dropdownlist which is inside a gridview on the click of a button?

I have a dropdownlist inside the gridview. Now i want when i click on a button then i can check the value of dropdownlist. I have fired rowcommand event of gridview for it but debugger is not able to go reach there..Please help me..My Code is
Protected Sub grd_Test_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grd_Test.RowCommand
If e.CommandName = "Select" Then
End If
End Sub
my Source code is
<asp:GridView ID="grd_UnAssignProperties" runat="server" AutoGenerateColumns="False"><Columns>
<asp:TemplateField HeaderText="Assign To">
<ItemTemplate>
<asp:DropDownList ID="drp_UnAssignProp" runat="server">
<asp:ListItem Value="" >Default</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns></asp:GridView><tr><td><asp:Button ID="btn_Save" runat="server" CommandName="Select" Text="Submit" />
try this
DropDownList ddl = (DropDownList)GridView1.Rows[e.RowIndex].Cells[0].FindControl("drp_UnAssignProp");
string val = ddl.SelectedValue;
try
string val = (DropDownList)GridView1.Rows[e.RowIndex].Cells[0]
.FindControl("drp_UnAssignProp").SelectedValue;
First of all, since the button btn_Save isn't inside the GridView, clicking on it won't raise the grd_Test_RowCommand, either move the button inside GridView or you have to raise it manually like this:
Copied from asp.net forum:
Protected Sub Button1_Click(sender As Object, e As EventArgs)
Dim commandArgs As New CommandEventArgs("Command Name Here", "Your Command Argument Here")
'You can pass any row
'You can also skip the row parameter and get the row from Command Argument
Dim eventArgs As New GridViewCommandEventArgs(GridView1.Rows(0), GridView1, commandArgs)
GridView1_RowCommand(GridView1, eventArgs)
End Sub
Now regarding your original question, this is how you can get the selected value of DropDownList inside RowCommand event:
Edit: Fixed code to get the current row, for which the RowCommand event was raised
Protected Sub grd_Test_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grd_Test.RowCommand
If e.CommandName = "Select" Then
Dim index As Integer = Convert.ToInt32(e.CommandArgument)
Dim row As GridViewRow = DirectCast(DirectCast(e.CommandSource, LinkButton).NamingContainer, GridViewRow)
Dim ddl as DropDownList = CType(row.FindControl("drp_UnAssignProp", DropDownList)
Dim selectedValue as String = ddl.Text
End If
End Sub

GridView Paging inside a repeater

I have a gridview nested within a repeater, and I'm trying to enable paging on the gridview without much success.
The gridview databound is like this
<asp:repeater....>
<asp:gridview id="GridView1" Datasource='<%# LoadData(CInt(Eval("Id"))) %>'
OnPageIndexChanging="GridViewPageIndexChanging" AllowPaging="true"
PageSize="10" ............. </asp:GridView>
</asp:repeater>
In the code behind my LoadData method get a list of objects:
Public Function LoadData(ByVal Id As Integer) As IList(Of Client)
Dim ds As IList(Of Client) = client.GetClientById(Id)
Return ds
End Function
And the event handler is as follow:
Protected Sub GridViewPageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
sender.PageIndex = e.NewPageIndex
End Sub
My code doesn't change the page in the gridview, am I missing something ?
Any help is very much appreciated.
You have to call DataBind().
Dim grid as GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
EDIT
Since I can't comment yet and creating another answer to an answer makes everything confusing, I'll just edit this one.
I'm afraid the Repeater is a wrong control to use for what you want. The problem stems from the fact that it does not preserve DataItem when GridView's page events fire. So the "id" gets evaluated into nothing and subsequently a zero. Btw, in C# you'd get a null exception.
I suggest you use the DataList instead:
<asp:DataList ID="DataList" runat="server" DataKeyField="id">
<ItemTemplate>
<asp:GridView ID="Grid" runat="server"
AllowPaging="true"
PageSize="2"
OnPageIndexChanging="Grid_PageIndexChanging"
DataSource='<%# GetData(DirectCast(DataList.DataKeys(DirectCast(Container, DataListItem).ItemIndex), Integer)) %>'
>
</asp:GridView>
<hr />
</ItemTemplate>
</asp:DataList>
With code behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
DataList.DataSource = New Integer() {1, 2, 3, 4, 5}.Select(Function(x) New With {.id = x})
DataList.DataBind()
End If
End Sub
Protected Function GetData(ByVal id As Integer) As String()
Dim arr As String() = New String(4) {}
For i As Integer = 0 To arr.Length - 1
arr(i) = String.Format("id {0}; grid item {1}", id, i)
Next
Return arr
End Function
Protected Sub Grid_PageIndexChanging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
Dim grid As GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
End Sub
This code works -- I tested. Although, personally I don't like using binding expressions.
I'm one step further ,
After I do the binding I got an exception on Eval.
I changed it in the datasource to <%#LoadData(DataBinder.Eval(Container.DataItem,"Id"))%>
I don't get the Eval exception anymore after the binding. However my grid still empty.
[update]
Ok I got it solved by keeping my Ids in hashtable and I rebind my gridview with the equivalent id from the hashtable.
It is all good now thanks everyone for your helps.
One thing I see if your markup. Your sample has the GridView directly within the Repeater control. You will need it within the ItemTemplate.
<asp:Repeater ID="rpt" runat="server" ...>
<ItemTemplate>
<asp:GridView id="gv1" runat="server" ...>
.
.
.
</asp:GridView>
</ItemTemplate>
</asp:Repeater>

Resources