repeater.findcontrol not working on content page - asp.net

I have a non content (no master) page with a repeater that performs as I want it to, but when I move the same code to a content page (with master), the findControl in a loop of RepeaterItems no longer works.
aspx:
<ItemTemplate>
<div class="row" id="qrow" runat="server" data-id='<%#Eval("callQuestionID") %>' data-type='<%#Eval("callQuestionResponseType") %>' data-parent='<%#Eval("callQuestionParent") %>'>
<div class="col-md-4">
<asp:Label ID="questonTextLabel" runat="server" Text='<%# Eval("callQuestionText") %>'></asp:Label>
</div>
<div class="col-md-4">
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
</div>
</div>
</ItemTemplate>
ItemDataBound exerp
Dim newRBY As New RadioButton
newRBY.InputAttributes.Add("data-id", CType(e.Item.DataItem, DataRowView)("callQuestionID"))
newRBY.InputAttributes.Add("data-idy", CType(e.Item.DataItem, DataRowView)("callQuestionID"))
newRBY.ID = "rby"
newRBY.Text = "Yes"
newRBY.GroupName = "qid" & CType(e.Item.DataItem, DataRowView)("callQuestionID")
CType(e.Item.FindControl("Panel1"), Panel).Controls.Add(newRBY)
Dim newRBN As New RadioButton
newRBN.InputAttributes.Add("data-id", CType(e.Item.DataItem, DataRowView)("callQuestionID"))
newRBN.InputAttributes.Add("data-idn", CType(e.Item.DataItem, DataRowView)("callQuestionID"))
newRBN.ID = "rbn"
newRBN.Text = "No"
newRBN.GroupName = "qid" & CType(e.Item.DataItem, DataRowView)("callQuestionID")
CType(e.Item.FindControl("Panel1"), Panel).Controls.Add(newRBN)
Post user interaction processing:
For Each questionRow As RepeaterItem In questionRepeater.Items
...
Dim rby As RadioButton = CType(questionRow.FindControl("rby"), RadioButton) ****** Fails Here *****
If rby.Checked Then
dataAccess.callQuestionAnswerTable_Insert(callIDInteger, CInt(rby.InputAttributes("data-id")), "true")
ElseIf CType(questionRow.FindControl("rbn"), RadioButton).Checked Then
dataAccess.callQuestionAnswerTable_Insert(callIDInteger, CInt(rby.InputAttributes("data-id")), "false")
End If
It fails in the post user interaction processing when trying to find 'rby'. The only difference in generated HTML is that in the content page the controls ids get a MainContent_ prefix.
What can I do to resolve this?

If the code is located on the child page, while the Repeater is located on the Master Page itself, you need to specify the Master page with FindControl and locate the Repeater there.
Dim rpt As Repeater = CType(Master.FindControl("Repeater1"),Repeater)
And then
For Each questionRow As RepeaterItem In rpt.Items
(translated from C# to VB with a code translator, so it may be a little off, in C# it is Repeater rpt = Master.FindControl("Repeater1") as Repeater;)

I found my problem. It was actually that I had the binding of the repeater in a
If Not IsPostBack Then
block and I should not have apparently.

Related

How to get Repeater's current ItemIndex in code behind

While Container.ItemIndex as a way to get current repeater's item index in data binding expression works perfectly fine <%# Container.ItemIndex %>, it does not work in pure code behind. Container is not declared or inaccessible.
How can I get repeater's current item index here:
<ItemTemplate>
<% If Container.ItemIndex = 2 Then %>
TRUE/some longer HTML here/
<% Else %>
false/some longer HTML here/
<% End If %>
</ItemTemplate>
EDIT
For cases with not much HTML code this will work, but I am looking for Code Render Block solution as per example above.
<%#: If(Container.ItemIndex = 2, "TRUE", "false") %>
Ok, just drop in a button and pick up the repeter row.
So, say we have this repeater markup:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div style="border-style:solid;color:black;width:290px;float:left;padding:10px">
<div style="padding:5px;text-align:right">
Hotel Name: <asp:TextBox ID="txtHotelName" runat="server" Text ='<%# Eval("HotelName") %>' />
<br />
First Name: <asp:TextBox ID="txtFirst" runat="server" Text ='<%# Eval("FirstName") %>' />
<br />
Last Name: <asp:TextBox ID="txtLast" runat="server" Text ='<%# Eval("LastName") %>' />
<br />
City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>' />
<br />
Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>'/>
<br />
Active: <asp:CheckBox ID="chkActive" runat="server" Checked = '<%# Eval("Active") %>'/>
<br />
<asp:Button ID="cmdRowC" runat="server" Text="Row Click" OnClick="cmdRowC_Click"/>
</div>
</div>
<div style="clear:both;height:5px"></div>
</ItemTemplate>
</asp:Repeater>
and our code behind to fill this repeater:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT * FROM tblHotels ORDER BY HotelName",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Repeater1.DataSource = cmdSQL.ExecuteReader
Repeater1.DataBind()
End Using
End Sub
And we now have this:
So now the button code. Note how I just dropped in a standard button.
But, we now can't double click on the button to automatic wire up and create a event.
BUT YOU CAN do this to create a event:
In the button code markup, type in OnClick=
WHEN YOU HIT "=", then intel-sense will pop up a dialog for you to create a button click event like this:
So, now click on create new event. It "seems" like nothing occured, but if we flip to code behind you find the click event stub.
So, now in our click event code we can easy pick up the current repeater row, the values and yes even the index.
The code works like this:
Protected Sub cmdRowC_Click(sender As Object, e As EventArgs)
Dim cBtn As Button = sender
Dim rRow As RepeaterItem = cBtn.Parent
Debug.Print("Row clicked = " & rRow.ItemIndex)
Debug.Print("First Name = " & DirectCast(rRow.FindControl("txtFirst"), TextBox).Text)
Debug.Print("Last Name = " & DirectCast(rRow.FindControl("txtLast"), TextBox).Text)
Debug.Print("Hotel Name = " & DirectCast(rRow.FindControl("txtHotelName"), TextBox).Text)
End Sub
output:
Row clicked = 1
First Name = Darcy
Last Name = Caroll
Hotel Name = Athabasca Hotel
So, just drop in a plane jane button. When you click on it the event stub runs, and as you can see, we pick up the "Repeater row item".
From that row, we can get the row index, and of course pluck out any other control value from that row using find control.
eg:
Dim txtHotel as TextBox = rRow.FindControl("txtHotel")
debug.print ("Hotel name = " & txtHotel.Text)
So, once you have the repeater row, you don't need some container.ItemIndex expression, since the row item lets you get the given index row with:
rRow.ItemIndex
So, ItemIndex is available, and is avilable regardless if you have or include or use the conttin.ItemIndex in the markup.
There is VERY LITTLE need to mess around with that code in the markup.
Note how VERY clean and simple the above is. I suggest you MAKE HUGE efforts to avoid dumping vb code inside of the markup like you are doing. If you even want to convert to c#, or even just maintain that code? Put that code in the code behind area - not in the markup.
As above shows, for repeating data etc., you can use a Repeater, or even often I use a listview - as it allows a repeating layout to be created automatic for you, and without having to write looping code.
******************** EDIT ***************************
Ok, now that we have this working, say we wanted to put in a message in the repeater that
This hotel is Active
or
This hotel is NOT active!
Ok, so in our markup, we could drop in a label like this:
And now from the repeater property sheet, double click here to create the item data bound event:
It is now a simple matter to put in our code logic for each row like this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
End Sub
And output is now this:
So, once again, to conditional format the repeater, add color to active hotel, or whatever? Use the item bound event.
Say i wanted add to above that the HotelName is to be color blue when active, then we could do this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
Dim txtHotel As TextBox = rRow.FindControl("txtHotelName")
If ckbox.Checked Then
txtHotel.BackColor = Drawing.Color.AliceBlue
End If
End Sub
Again, nice easy clean code - no mess markup. We seperate the code logic from the markup.
Output now is this:
Again, note how we did not even write ANY looping code here!!!!
So you want to leverage the built in options for the repeater, and for a GridView, listView, and a repeater?
Use the row data bind event - it lets you format, even do math, or whatever you want for EACH row of the repeating controls. And as you can see, its plain jane easy to write code as a bonus.

Avoid postback on TreeView SelectedNodeChanged (inside jquery dialog)

What I am attempting to achieve is basically this:
user clicks on save as button
dialog "pop-up" shows that has report categories and name entry
user enters a name, or selects category which loads old reports
backend will get the values from dialog and use those to update reports in database
My issue is that when I fire the MyTreeView.SelectedNodeChanged event, I am redirected to the aspx page that I'm showing in my dialog pop-up. Is there anything I can do to prevent this, or contain the postback? I included my code, but I'm guessing this will be something I will have to account for in aspx?
Here's some code:
ReportSave.aspx -- in dialog window
<%# Page Language="VB" AutoEventWireup="false" CodeFile="ReportSave.aspx.vb" Inherits="ReportSave" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Save Report As</title>
<link href="ReportSaveStyle.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<form id="formReportSave" runat="server">
<div class="container">
<asp:Label class="report-list-title" ID="lblReportList" runat="server" Text="Report List"></asp:Label>
<asp:TreeView class="report-list-items" ID="trvReportList" runat="server"></asp:TreeView>
<asp:Label class="category-tree-title" ID="lblReportCategory" runat="server" Text="Report Category"></asp:Label>
<asp:TreeView class="category-tree-items" ID="trvCategoryView" runat="server"></asp:TreeView>
<asp:Label class="save-input-title" ID="lblReportName" runat="server" Text="Report Name"></asp:Label>
<asp:TextBox class="save-input-textbox" ID="tbReportName" runat="server"></asp:TextBox>
<asp:Button class="save-button1" ID="btnOK" runat="server" Text="OK" />
<asp:Button class="save-button2" ID="btnCancel" runat="server" Text="Cancel" />
</div>
</form>
</body>
</html>
Backend code - ReportSave.aspx.vb
Private Sub trvCategoryView_SelectedNodeChanged(sender As Object, e As EventArgs) Handles trvCategoryView.SelectedNodeChanged
Try
'Dim li As ListItem
'li = cblCategoryView.SelectedItem
Dim node As TreeNode
node = trvCategoryView.SelectedNode
' handle all categories
If node.Value.ToString.ToUpper = "NEW CATEGORY" Then
Dim strNC As String = InputBox("Enter Name for New Category", "Create Category")
If strNC = "" Then
Exit Sub
End If
If strNC.ToUpper = "NEW CATEGORY" Then
ClientScript.RegisterStartupScript(Me.GetType(), "myalert", "window.alert('You can't have a Category Called New Category. Sorry!');", True)
Exit Sub
End If
Dim conn As New SqlClient.SqlConnection(_ConnectionString)
conn.Open()
Dim cmd As New SqlClient.SqlCommand("Select recordno from Reports where ReportType = '" & strNC & "'", conn)
Dim strresult As String = cmd.ExecuteScalar
If IsNothing(strresult) Then
Dim temp As TreeNode = New TreeNode(strNC, strNC, "Images/file.png")
' Dim temp As ListItem = New ListItem(strNC, strNC)
'lvCategoryView.Items.Add(temp)
'SetSelectedListItem(lvCategoryView.Items(lvCategoryView.Items.Count - 1))
'cblCategoryView.Items.Add(temp)
trvCategoryView.Nodes.Add(temp)
FillReports()
lblReportList.Text = "Report List for Group " & trvCategoryView.SelectedValue.ToString
' cblCategoryView.SelectedValue
ClientScript.RegisterStartupScript(Me.GetType(), "myalert", "window.alert('That Report Group Already Exists');", True)
End If
cmd.Dispose()
cmd = Nothing
conn.Close()
conn.Dispose()
conn = Nothing
Exit Sub
Else
'SetSelectedListItem(li)
FillReports()
lblReportList.Text = "Report List for Group " & trvCategoryView.SelectedValue.ToString
'cblCategoryView.SelectedValue.ToString
End If
Catch ex As Exception
End Try
End Sub
Thanks for any help in advance! I am new to Web Development as well as ASP.NET. :)
I am making the assumption that you are loading this form into an iframe, and would guess that the problem lies in the implementation of the MyTreeView.SelectedNodeChanged event or the parent page itself.
Thinking outside the box, Web Forms may have alternate solutions to accomplish your objectives. The implementation of an iframe would be my least favorite. Depending on your specific requirements, these options may work better for you.
Nested Masterpages
Re-usable User Control (ascx) in overlay (popup) DIV element
Update Panel in overlay (popup) DIV element
AJAX post to Handler (ashx)

SelectedIndexChange Not Firing

I'm having issue with a dropdownlist updating a textbox, both held within a listview, within an update panel which in turn is in an item template.
Updated
I have got this working with the same code without the above containers in a different web page on the same project, however having trouble linking it with the lisview and other containers.
I am unsure of where the problem lies, the onClick isn't firing unless there's a call back to the server, regardless whether the drop down is contained within the containers mentioned above.
Any help would be greatly appreciated, thanks in advance.
Using asp (1st) and VB code behind (2nd).
<InsertItemTemplate>
<asp:panel runat="server" ChildrenAsTriggers="true" UpdateMode="Always">
<asp:ListView ID="ListView1" runat="server" InsertItemPosition="FirstItem" IAllowPaging="True" EnableViewState="true">
<tr>
<td>
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("Details")%>' TextMode="MultiLine" />
</td>
<td>
<asp:DropDownList ID="DLL" runat="server" OnSelectedIndexChanged="DLL_SelectedIndexChanged" AutoPostBack="true "EnableViewState="true">
<asp:ListItem>Select</asp:ListItem>
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="2">No</asp:ListItem>
<asp:ListItem Value="3">Maybe</asp:ListItem>
<asp:ListItem Value="4">I dont know</asp:ListItem>
<asp:ListItem Value="5">Can you repeat</asp:ListItem>
<asp:ListItem Value="6">the question</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
</asp:panel>
</InsertItemTemplate>
Code behind
Protected Sub DDL_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
Dim listviewItemThing = DirectCast(sender.parent.NamingContainer, ListViewItem)
Dim tb As TextBox = DirectCast(ddl.NamingContainer.FindControl("TextBox2"), TextBox)
If ddl.SelectedValue = 1 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\1.txt")
ElseIf ddl.SelectedValue = 2 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\2.txt")
ElseIf ddl.SelectedValue = 3 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\3.txt")
ElseIf ddl.SelectedValue = 4 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\4.txt")
ElseIf ddl.SelectedValue = 5 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\5.txt")
ElseIf ddl.SelectedValue = 6 Then
tb.Text = My.Computer.FileSystem.ReadAllText("E:\Users\han\Documents\Templates\6.txt")
Else
tb.Text = ""
End If
End Sub
Update 2
As per request please see attached screen shot of browser console error in debug on VS2013
And expanded error.
Update 3
Added JQuery to try to force PostBack.
function JsFunction() {
__doPostBack('DLL_SelectedIndexChanged', '');
}
ASP link to JQ
<asp:DropDownList ID="DDL" runat="server" Width="120px" OnSelectedIndexChanged="DDL_SelectedIndexChanged" AutoPostBack="true" CausesValidation="false" EnableViewState="true" onchange="javascript:JsFunction()">
You have correct code for your drop down list, so error in other place.
As you see in error message: when you try submit form problem with HtmlEditorExtender.
So just remove or disable it for quick fixing problem.
As for error with HtmlEditorExtender we need a little bit information, of course, if you still need solve it.
Assuming these controls are within the ItemTemplate of your ListView:
FindControl("DDL") won't work, because it's trying to find the control within the page;
ListView1.FindControl("TextBox2") won't work, because there will be multiple instances of TextBox2 within the ListView.
Try this instead:
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
Dim tb As TextBox = DirectCast(ddl.NamingContainer.FindControl("TextBox2"), TextBox)
I assume you haven't got the typo in your actual code:
OnSelectedIndexChanged="DLL_SelectedIndexChanged"
Where the event handler is DDL_SelectedIndexChanged.
Have you put a breakpoint on to check whether the event handler is not being called or if it is bailing out at some point after it fails to do the cast you want it to do?

PreviousPage Findcontrol Issue

I need to get the text of the following linkbutton that is set to postback to another page:
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# Bind("computername") %>' PostBackUrl="~/assetdetails.aspx" CommandName="Select">LinkButton</asp:LinkButton>
</ItemTemplate>
I have tried many things in the receiving pages load event but this is what i ended up with:
Dim GV As GridView = TryCast(PreviousPage.Master.FindControl("content").FindControl("GridView2"), GridView)
Dim LB As LinkButton = TryCast(GV.SelectedRow.Cells(0).FindControl("LinkButton1"), LinkButton)
lblAsset.Text = LB.Text
Obviously it doesnt (returns blank, not null) work or i would not be making this post. :)
Please help!
You are doing it wrong way.
Here GridView is inside a Content Page ( which uses a master page), so access the GridView present originally in content page as:
If (Not (Me.Page.PreviousPage) Is Nothing) Then
Dim ContentPlaceHolder1 As Control =
Me.Page.PreviousPage.Master.FindControl("ContentPlaceHolder1")
Dim GV As GridView =
CType(ContentPlaceHolder1.FindControl("GridView1"), GridView)
Dim LB As LinkButton =
TryCast(GV.SelectedRow.Cells(0).FindControl("LinkButton1"), LinkButton)
lblAsset.Text = LB.Text
End If
GridView and other contents are present inside ContentPlaceHolder controls actually.

Gridview in user control page (ascx) is null

I have a page from where a user can search for items and so on. I use a .ascx page to display the result in a grdview.
The aspx page only has a seacrh box and a button and on button click I want to pass the value from inside the textbox to the ascx page and have the gridview populate with the result. But after debugging I found that the gridview is set to null after the button click. All other values are there and the result comes back from the database.
Can some one please help. I have been looking for a solution for last few hours and have treid a few diffeerent things but still not getting anywhere.
thanks in advance
EDIT
Here is my code
This is the aspx page.
<%# Register Src="Search.ascx" TagName="Search" TagPrefix="uc1" %>
<form id="form1" runat="server">
<div class="content">
<div style="padding:5px;">
<b>Search</b>: <asp:TextBox runat="server" ID="txtSearch" />
<asp:RequiredFieldValidator ErrorMessage="*" ValidationGroup="SearchGroup" ControlToValidate="txtSearch" ID="RequiredFieldValidator1"
runat="server" />
</div>
<div style="padding:5px;">
<asp:Button Text="Search" runat="server" ValidationGroup="SearchGroup" OnClick="btnSearch_Click" ID="btnSearch" />
</div>
</div>
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<div class="Results">
<uc1:Search ID="UserControl1" runat="server" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
In the ASCX page I have the following
The code behind
Dim test As Object = txtSearch.Text
Dim StockList As cls_Stock_Col = MyLOTSDB.LoadStock_Col()
Try
Dim dt As DataTable = New DataTable()
Dim dcol As New DataColumn("TradeName", GetType(System.String))
dt.Columns.Add(dcol)
'Create an ID column for adding to the Datatable
dcol = New DataColumn("PackSize", GetType(System.String))
dt.Columns.Add(dcol)
dcol = New DataColumn("PLU", GetType(System.String))
dt.Columns.Add(dcol)
dcol = New DataColumn("SOH", GetType(System.String))
dt.Columns.Add(dcol)
dcol = New DataColumn("RetailAsCurrency", GetType(System.String))
dt.Columns.Add(dcol)
For Each col As DataColumn In dt.Columns
'Declare the bound field and allocate memory for the bound field.
Dim bfield As New BoundField()
'Initalize the DataField value.
bfield.DataField = col.ColumnName
'Initialize the HeaderText field value.
Dim DisplayName As String = ""
Dim DataFormat As String = ""
Dim FieldType As Type = col.GetType()
Dim StringLength As Int32
GetFieldDetails(TheType, col.ColumnName, DisplayName, DataFormat, FieldType, StringLength)
bfield.HeaderText = DisplayName
If (DataFormat = "$0.00") Then
bfield.DataFormatString = "{0:C2}"
End If
bfield.SortExpression = "col.ColumnName"
'Add the newly created bound field to the GridView.
GridView1.Columns.Add(bfield)
Next
GridView1.DataSource = StockList
GridView1.DataBind()
Catch ex As Exception
End Try
I can debug and the error is thrown when I try to add the column to the gridview,
Thanks again
The aspx page only has a seacrh box and a button and on
button click I want to pass the value from inside the textbox to the ascx page
You can do this by specifying a public property on your ascx control which you can access on calling page.
Inside your ascx code behind
private string searchText ;
Public string SetSearchText
{
get { return searchText; }
set { return searchText; }
}
In your calling page on button click, just set the property of the ascx control
Inside your main page on button click
YourAscxControl.SetSearchText= yourTextBox.Text.Trim();
User Dynamic Content Place Holder .
Refer to following links they might help:-
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
http://www.codeproject.com/Articles/18080/Solve-Dynamic-Control-Problem-With-PostBack

Resources