I can access the text within a textbox within my repeater, but I am unable to pull the text value from a label within my repeater.
The repeater is populated from a datatable with row(x) being filled by sqlreader(x), I don't know if that makes a difference.
I cannot use javascript for this. I need to access the label value from the codebehind.
<asp:label id="weiLabel" runat="server">
<%#DataBinder.Eval(Container, "DataItem.weiLabel")%>
</asp:label>
is the markup
I can access a textbox on the same row using:
featTable.Controls(1).Controls(1).FindControl("costText")
and retrieve the textbox.text, but using the same statement for the label gives me {text=""}.
I have verified that the clientID of control that is returned with findcontrol is correct (featTable__ctl1_weiLabel)
Thanks for any help
Can you try declaring your label like this:
<asp:label id="weiLabel" runat="server" Text='<%#DataBinder.Eval(Container, "DataItem.weiLabel")%>' / >
You can also try putting in the value into your label from the code behind using the databound method. I find it a bit easier to debug and cleaner then putting it in the html
Private Sub repPoliList_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repPoliList.ItemDataBound
If (e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim dr As DataRowView = CType(e.Row.DataItem, DataRowView)
Dim weiLabel As System.Web.UI.WebControls.Label= CType(e.Item.FindControl("weiLabel"), System.Web.UI.WebControls.Label)
weiLabel.text= dr("ColumnFromDatabase").toString
End If
End Sub
Related
I have a GridView. I want the content of the cells, the actual detail data, to be html-encoded. But I want to keep the raw HTML in the heading.
That is, the heading in this case is the name of a language and the ISO code, for example "English (EN)". I want the name and code on separate lines, so I'm specifying the heading as "English<br/>(EN)".
But for the content, I want to see any HTML. If it says "<p>foobar</p>" I want the p-tags to display.
If I say "htmlencode=false", then the heading doesn't get encoded, but neither does the data.
Is there any way to say, html-encode the data, but not the heading?
If it matters, I'm building the columns in code rather than with tags in the ASP file, depending on which languages I find in my data. So here's how I'm creating the column:
For Each row As DataRow In ds.Tables(0).Rows
Dim iso2 = row("language")
Dim name = row("name")
... other code ...
Dim head = String.Format("{0}<br/>({1})", name, iso2)
gvSnippets.Columns.Add(New BoundField With {.HeaderText = head, .DataField = iso2, .HtmlEncode = False})
... other code ...
End For
(My first draft did not set HtmlEncode.)
Curious observation: In my first couple of test runs, the data did not include any HTML or entities, and the HTML in the heading was NOT encoded, I got the line break and not "<br/>". Then I did a test where there were entities in the data and the entities got html-encoded ... and so did the header. So like, ASP is apparently saying that by default, if the data has no HTML but the heading does, then don't HTML-encode the heading. But if the data has HTML, then HTML-encode both the data and the heading. So like, it's deciding dynamically whether to html-encode the heading or not.
In reply to #fnostro, here's the markup for the GridView:
<asp:GridView ID="gvSnippets" runat="server" AutoGenerateColumns="False" SkinID="skin3" EmptyDataText="No records found" Visible="false">
</asp:GridView>
There is no <Columns> markup. I build the columns completely in code. I haven't tested if the same behavior occurs in what I assume is the more normal case where you specify columns with markup.
Add these lines of code to the beginning of your loop
row("language") = HttpUtility.HtmlEncode(dr("language"))
row("name") = HttpUtility.HtmlEncode(dr("name"))
Based on my reading of the information provided in your post I have the following suggestions:
You should isolate data formatting from raw data.
Your DataTable is the data source for the GridView. The DataTable should contain only raw data, completely unformatted and unadulterated.
The DataTable gets bound to the Gridview by setting the GridView DataSource and making a call to DataBind(). Calling gvSnippets.Databind() will trigger all the databinding events associated with Gridviews which will allow you to:
Manage simple formatting and binding in the GridView Columns in the aspx markup.
Handle more complicated formatting in the code behind for specific GridView events like the RowDataBound event.
Regarding the GridView Header: HeaderText appears once at the top of the Gridview and is stored internally in GridView.HeaderRow, not on a per row basis even though every bound field has a HeaderText property.
Example excerpt gvSnippets Markup per your update:
<asp:GridView ID="gvSnippets" runat="server"
AutoGenerateColumns="False" SkinID="skin3"
EmptyDataText="No records found" Visible="false">
</asp:GridView>
Then you can do things like this in the Code Behind:
Public Class __JunkWebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Fill Dataset first, then:
gvSnippets.DataSource = ds.Tables(0)
' Add Columns...
gvSnippets.Columns.Add(...)
gvSnippets.Columns.Add(...)
gvSnippets.Columns.Add(...)
. . .
' This will trigger data binding events
gvSnippets.DataBind();
End Sub
Private Property HeaderTextLanguage As String
Private Property HeaderTextLanguageIso As String
Dim NeedHeaderText As Boolean = False
Private Sub gvSnippets_DataBinding(sender As Object, e As EventArgs) Handles gvSnippets.DataBinding
NeedHeaderText = True
End Sub
Private Sub gvSnippets_DataBound(sender As Object, e As EventArgs) Handles gvSnippets.DataBound
Dim this As GridView = sender
this.Columns(0).HeaderText = String.Format("{0}<br>({1})", HeaderTextLanguage, HeaderTextLanguageIso)
End Sub
Private Sub gvSnippets_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gvSnippets.RowDataBound
Dim this As GridView = sender
Dim drv As DataRowView = e.Row.DataItem
If e.Row.RowType = DataControlRowType.DataRow Then
If NeedHeaderText Then
HeaderTextLanguage = drv("language")
HeaderTextLanguageIso = drv("iso")
NeedHeaderText = False
End If
e.Row.Cells(0).Text = Server.HtmlEncode(drv("Somefieldnameofyours"))
End If
End Sub
End Class
Addendum Dealing with Dynamic cells
For a GridView defined as:
<asp:GridView ID="gvSnippets" runat="server"
AutoGenerateColumns="False">
</asp:GridView>
I don't know how you're populating your ds but I'm using a SqlDataSource to fill a table in the Code Behind. Note there is no GridView DataSourceID above:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="select top 10 user_id, user_name, user_logon, 'English' as language, 'en' as iso from tbl_users"
ConnectionString='<%$ ConnectionStrings:MyConnectionString %>'>
</asp:SqlDataSource>
Then in the Code Behind I can do this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
GetDataSetAndPopulate(gvSnippets)
End Sub
Private Sub GetDataSetAndPopulate(gv As GridView)
Dim view As DataView = SqlDataSource1.Select(DataSourceSelectArguments.Empty)
Dim table As DataTable = view.ToTable()
Dim ds As DataSet = New DataSet()
ds.Tables.Add(table)
For Each dc As DataColumn In ds.Tables(0).Columns
Dim field As New BoundField
field.DataField = dc.ColumnName
field.HeaderText = dc.ColumnName
gv.Columns.Add(field)
Next
gv.DataSource = ds
gv.DataBind()
End Sub
And now the Gridview is populated dynamically and you can still handle all the formatting during the DataBinding events as needed.
Here's a solution I came up with that works in my particular case.
I am building the data to populate the GridView in code. I create a DataTable, add columns to it, and then populate those columns. Like:
dim dslang=GetListOfLanguages()
dim dtgv=new DataTable()
for each row as DataRow in dslang.tables(0).rows
dim language_name=row("name")
dim language_code=row("code")
dtgv.columns.add(String.format("{0}<br/>({1})",language_name, language_code)
end for
... bunch of other stuff ...
... inside a loop that reads the data ...
dim outrow=dtgv.NewRow()
... get data for a specific language ...
outrow(language_code)=text
... later ...
my_gridview.datasource=dtgv
my_gridview.databind()
So my solution:
When creating the GridView, set HtmlEncode=false. This makes the header display correctly.
When populating the data, say
outrow(language_code)=HttpUtility.HtmlEncode(text)
So I add the data to the datatable that will ultimately be used as the datasource for the gridview already encoded, so I don't need to rely on the Gridview encoding it.
I consider this a mediocre solution, as it only works because I am populating GridView from a DataTable that I build with code. If I was populating the GridView directly from a DataSource specified in markup, or from a DataSet created by a database query, there'd be no convenient place to put the HttpUtility.HtmlEncode call.
I am using an OnItemDataBound event to attempt to activate a disabled button in a repeater. Quite simply, if the event is triggered, I know there are items in the repeater and therefore want to enable the button. Where I am getting stuck is on casting the button in the function so I can enable it. The relevant part of the repeater code is below:
<asp:Repeater ID="RptEnterHours" runat="server" DataSourceID="SQL_EmployeeGetTimesheet" ClientIDMode="Predictable" OnItemDataBound="RptEnterHours_Bound">
'.....Irrelevant code.....
<FooterTemplate>
<asp:Button Enabled="false" ID="SubmitTimesheets" Text="Submit All Timesheets" OnClick="processTimesheetEntry" runat="server" OnClientClick="checkValues();" />
</FooterTemplate>
</asp:Repeater>
This is my code behind:
Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)
'Exposes the Submit All Timesheets button if timesheets are available.
If (e.Item.ItemType = ListItemType.Item) Or _
(e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim sButton As Button = TryCast(Me.FindControl("SubmitTimesheets"), Button)
sButton.Enabled = True
End If
End Sub
This and all other attempts has yielded the dreaded "Object reference not set to an instance of an object" message. Can anyone tell me what I am doing wrong and why my code behind won't find the button?
please try this i am sure it will help you.
If e.Item.ItemType = ListItemType.Footer Then
Dim btn as new button
btn = CType(e.Item.FindControl("SubmitTimesheets"), Button)
btn.enabled = true
End If
You're restricting it to looking within the item and alternating item templates.
Change this:
If (e.Item.ItemType = ListItemType.Item) Or _
(e.Item.ItemType = ListItemType.AlternatingItem) Then
To:
If (e.Item.ItemType = ListItemType.Footer) Then
You want to test for e.Item.ItemType = ListItemType.Footer. Item and AlternatingItem are used for the actual data records, not the footer. Therefore, the button indeed does not exist for Items and AlternatingItems.
Then, you will want to add a test for whether the RptEnterHours.DataSource object has records. For this, you will need to cast the RptEnterHours.DataSource to whatever type the data source is.
So, basically something like this. You will obviously need to change it to fit your code:
Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)
'Exposes the Submit All Timesheets button if timesheets are available.
If (e.Item.ItemType = ListItemType.Footer) Then
Dim sButton As Button = TryCast(Me.FindControl("SubmitTimesheets"), Button)
Dim myDataSource = CType(RptEnterHours.DataSource, MyDataSourceType)
sButton.Enabled = (myDataSource.Count > 0)
End If
End Sub
It's been a little while since I've worked with web forms, but I believe the problem is two fold.
When the item type is Item or AlternatingItem then you know you have data in the repeater. In those cases you could set an instance level flag to indicate that you have items.
Then, when the item type is footer AND you have items you want to enable to button. The way to do this is mentioned in an unaccepted answer to the question linked to by #codingkiwi.com, but I believe the problem is the context in which you're calling FindControl. You are calling Me.FindControl which will search the level 1 children of the page (or user control, or control, or whatever Me is a reference to). You want to be searching the child controls of the actual repeater element, which in this case is the footer. So the search becomes e.Item.FindControl.
It should be noted that there are probably more elegant ways to detect whether or not a repeater control has elements. Perhaps all you need to check for in the OnDataBound event is the footer item, and then look for something like: (my VB may be a bit rusty too)
If (Me.RptEnterHours.Items IsNot Null AndAlso Me.RptEnterHours.Items.Any()) Then
Not sure why its just not enabled in the first place, but this will work since it will fire for the footer after the Item/AlternatingItem types:
Private m_bolEnableButton As Boolean = False
Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)
'Exposes the Submit All Timesheets button if timesheets are available.
If (e.Item.ItemType = ListItemType.Item) Or _
(e.Item.ItemType = ListItemType.AlternatingItem) Then
'"if the event is triggered, I know there are items in the repeater and therefore want to enable the button"
m_bolEnableButton = True
End If
If e.Item.ItemType = ListItemType.Footer Then
If m_bolEnableButton Then
Dim sButton As Button = TryCast(e.Item.FindControl("SubmitTimesheets"), Button)
sButton.Enabled = True
End If
m_bolEnableButton = False
End If
End Sub
The reason you get the Object null reference exception is because you are fixated on the cast, which isn't causing the problem. You can generally safely cast the results of FindControl implicitly. What you need to explicitly check for is a null reference AFTER the FindControl results are captured.
Also, you should be looking for ListItemType.Footer so you can reference the footer row.
Finally, FindControl() is not recursive. It only finds controls within the top-level naming container. In most databound controls, each row represents its own naming container, so you must FindControl within the row you want to search. When you use Me, it refers to the page. You should instead use e.Item.FindControl().
Code:
Dim bRecordsFound as Boolean = False
Sub RptEnterHours_Bound(Sender As Object, e As RepeaterItemEventArgs)
If (e.Item.ItemType = ListItemType.Item) Or _
(e.Item.ItemType = ListItemType.AlternatingItem) Then
bRecordsFound = True
End If
If (e.Item.ItemType = ListItemType.Footer) And (bRecordsFound) Then
Dim sButton As Button = e.Item.FindControl("SubmitTimesheets")
If sButton IsNot Nothing Then
sButton.Visible = True
End If
End If
End Sub
I'm having lots of trouble understanding how repeaters are supposed to work and how I'm supposed to use them. Basically, I have a label, a set of image buttons, and a div within a repeater. When you click on the button, I want to populate the div that was created with these repeaters (so a different div for each iteration of the repeater).
It seems so simple, yet I can't get anything to work. Please help me!
Here is some of my code if that helps.
(my data source)
<asp:sqldatasource runat="server" id="dtsSpecialNotes" connectionstring="connection string" providername="System.Data.SqlClient"> /asp:sqldatasource
(my repeater)
<asp:Repeater id="rptSpecialNotes" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
</ItemTemplate>
</asp:Repeater>
(some code behind, I have a method to populate the repeater called on page load)
rptSpecialNotes.DataSource = dtsSpecialNotes
rptSpecialNotes.DataBind()
Dim imbMotion As New ImageButton
Dim imbAttachments As New ImageButton
imbMotion.ImageUrl = "images/controls/Exclaim.png"
imbMotion.Width = "40"
imbMotion.Height = "40"
imbMotion.AlternateText = "Add Motion"
imbMotion.ID = "imbMotion" & listSpecialNotesCounter
imbAttachments.ImageUrl = "images/controls/Documents.png"
imbAttachments.Width = "40"
imbAttachments.Height = "40"
imbAttachments.AlternateText = "Add Document"
imbAttachments.ID = "imbAttachments" & listSpecialNotesCounter
rptSpecialNotes.Controls.Add(lblTitle)
rptSpecialNotes.Controls.Add(imbMotion)
Here are the problems I'm having:
I can't get the repeater to iterate. It's only firing off once and then stops.
I can't get a label with the repeater data source's Subject (a field in my database) to appear.
I really appreciate any help. I just can't grasp these repeater controls.
What you want to do is populate your repeater using the ItemDataBound event as opposed to going through the item collection. That will be called for each of the items that are in the collection you assigned to the DataSource.
This is what I do when working with repeater data binding and the ItemDataBound event, I'll use a list of news items for this example:
' Bind my collection to the repeater
Private Sub LoadData()
Dim newsList As List(Of News) = dao.GetNewsList()
rptrNews.DataSource = newsList
rptrNews.DataBind()
End Sub
' Every item in the data binded list will come through here, to get the item it will be the object e.Item.DataItem
Protected Sub rptrNews_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
' Get the current item that is being data bound
Dim news As News = DirectCast(e.Item.DataItem, News)
' Then get all the controls that are within the <ItemTemplate> or other sections and populate them with the correct data, in your case it would be an image
Dim ltlHeadline As Literal = DirectCast(e.Item.FindControl("ltlHeadline"), Literal)
Dim ltlContent As Literal = DirectCast(e.Item.FindControl("ltlContent"), Literal)
ltlHeadline.Text = news.Headline
ltlContent.Text = news.Teaser
End If
End Sub
Alternatively, you could do it all in the Markup Code and only assign the datasource and call data bind in the code behind. To achieve this you could define your ItemTemplate as follows (again with the news e.g.):
<ItemTemplate>
<tr>
<td><%#Container.DataItem("Headline")%></td>
<td><%#Container.DataItem("Teaser")%></td>
</tr>
</ItemTemplate>
I have this label inside a repeater
<asp:Label id="lblsub" runat=server text="sdds" />
I am trying to change the text of this label,this is the code behind
For Each Item As RepeaterItem In dg.Items
Dim l As New label
l = CType(Item.FindControl("lblsub"), System.Web.UI.WebControls.Label)
l.text="test"
Next
unfortunately this code doesn't work for me ,the text value doesn't change ,so I will be very happy to some help here
thanks
See my answer in this question. Believe it will solve your issue.
Getting the databound value from repeater control in asp.net
EDIT
First of all, make sure you always use quotes in your markup:
<asp:Label ID="lblsub" runat="server" Text="sdds" />
Try something like this in your code behind. Forgive me if my VB is a little rusty:
For Each Item As RepeaterItem in dg.Items
Dim l As Label = CType(Item.FindControl("lblsub"), Label)
l.Text = "test"
Next
There were just a couple little problems with syntax. I don't know if they are causing your issue, but best get the easy stuff out of the way first.
When is that bit of code being ran?
Make sure you are not rebinding the repeater afterwards by doing the following in your Page_Load:
Sub Page_load
If not Page.IsPostBack Then
BindRepeater()
End If
End Sub
If you need to do this bit of code every time the repeater is bound, then put your code into the DataBound event:
Protected Sub dg_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles dg.ItemDataBound
Select Case e.item.itemtype
Case ListItemType.Item, ListItemType.AlternatingItem
Dim l As Label = e.Item.FindControl("lblsub")
l.Text = "foo"
End Select
End Sub
I haven't got any programming software with me so unsure of the syntax
C# code sample (it should be inside method or page_load)
foreach (RepeaterItem rt in MyRepeater.Items)
{
Label l = ((Label)rt.FindControl("lblPrice"));
l.Text = "200";
}
I have LinkButton and HiddenField in a list view. I want to get the hidden value from HiddenField, so I can store it in Session and when a LinkButton is clicked it transfer the hidden value ( stored in Session) to another page. But I get this error message "Object reference not set to an instance of an object." Here's the function:
Protected Sub lvTimeSheet_ItemCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewCommandEventArgs) Handles lvTimeSheet.ItemCommand
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId"), HiddenField)
Dim myId As String = id.Value.ToString
Session("myId") = myId
Server.Transfer("Destination.aspx")
End Sub
The mark-up
</asp:LinkButton><asp:HiddenField ID="hfTimeSheetId1" runat="server" Value='<%# Eval("hfTimeSheetId") %>' />
Every time the LinkButton is clicked, it causes error with above error message. Thank you for any input.
My guess would be that the FindControl isn't finding the hfTimeSheetId control within the row. Do you have it designated as a managed control (i.e. runat="server")?
Also, it might help if you provided the ASPX code to see how you're defining the controls.
The FindControl is returning null, hense the exception. Try changing it to:
Dim id As HiddenField = TryCast(e.Item.FindControl("hfTimeSheetId1"), HiddenField)