ASP.NET Repeater - HiddenField working without being declared - asp.net

Using ASP.NET 4.0
Bit of a strange one here, my code works but I don't know why!
So I have some HTML like so:
<asp:Repeater runat="server" ID="uxMyRepeater" ClientIDMode="Predictable">
<ItemTemplate>
<asp:Button runat="server" Text="Submit" />
<asp:HiddenField runat="server" ID="uxIsVisibleHiddenField" Value="0" />
</ItemTemplate>
</asp:Repeater>
And the back end:
Protected Sub uxMyRepeater_ItemCommand(source As Object, e As RepeaterCommandEventArgs) Handles uxMyRepeater.ItemCommand
uxIsVisibleHiddenField.Value = "1"
End Sub
So for some reason this works, usually I would expect to have to declare uxIsVisibleHiddenField in uxMyRepeater_ItemCommand like so:
Dim uxIsVisibleHiddenField As HiddenField = DirectCast(e.Item.FindControl("uxIsVisibleHiddenField"), HiddenField)
But in this particular case it works without the declarative statement. Can anyone shed any light on why it would do this?
Please note this is sample code only, not my actual code.
EDIT
Forgot to mention there is an UpdatePanel around each RepeaterItem, removing this causes Visual Studio to give me an error that'd I'd expect: 'uxIsVisibleHiddenField' is not declared. It may be inaccessible due to its protection level.

This could only happen if you have a control with the same ID that sits outside of the repeater. You won't have ID clashes because the repeater is a naming container.

Do you have any AlternatingItemTemplate ? It might be declared in that particular area and remained unnoticed.

After a lot of debugging the only thing I can say is that when I have an UpdatePanel inside the Repeaters ItemTemplate I don't need to declare the controls inside the ItemTemplate when accessing them in the DataBind event, very strange. Taking out the UpdatePanel causes complier errors so the UpdatePanel must be doing some auto hook-up between the Repeater and the controls.
Thanks for all your suggestions.

Related

ASP.NET GridView empty on postback

Having an issue with an ASP.NET GridView is empty on postback that I need some help with. I think it may have something to do with the ViewState not being setup. Anyhow I originally had the code working on single user-form until I refactored code.
Now to paint the picture I have now both a master page and a base form. My master page has the place holder and on my actual user-form I have placed the GridView within the place holder bounds as follows:
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolderMainBody" Runat="Server">
<asp:GridView ID="data" runat="server" AutoGenerateColumns="false" EnableViewState="true" ...>
...
</asp:GridView>
</asp:Content>
One of fields in the GridView is an editable comments field mutli-line textbox (the rest are non editable):
<asp:TemplateField HeaderText="Comments">
<ItemTemplate>
<asp:TextBox ID="TextBoxComments" runat="server" TextMode="MultiLine" Rows="4" Columns="40" Text='<%# Bind("Comment")%>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBoxCommentsEdit" runat="server" TextMode="MultiLine" Rows="4" Columns="40" Text='<%# Bind("Comment")%>' />
</EditItemTemplate>
</asp:TemplateField>
I edit one of the rows and click a submit button to postback. The GridView has 10 rows to enter into however on postback there are zero rows so my saving is lost!
My base form contains the code in the OnInit event to load the submit button and thus also handles the click event.
My OnLoad event I call the base Onload which inturn calls my user form's Page_Load handler code which has one line of code namely:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
MyBase.data = Me.data
End Sub
and in the BaseForm is declared as:
Protected WithEvents data As GridView
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
If Not Page.IsPostBack Then
...
BindData(...)
...
End If
End Sub
in this way I can also handle all GridView events in the BaseForm.
So somewhere between the master/baseform/userform/viewstate relationship my GridView data is lost on PostBack. Any ideas?
On your Page_Load, bind the data only if IsPostBack is false.
You click on submit button that submit button fire RowUpdating event and that event contain query for update database table and after executed update query call BindData() function in your code .
Three in row I think for myself answering my own question - hooray! I do not know if that makes me intelligent or dumb because I have to search for more that a day to find a solution. Perhaps I did not give out enough information or it was not clear and this is what happens when you do things for the first time and you do not have a clue what you are doing. The vital information which was maybe not implied but hinted at, which I will spell it out for anyone else that might have the same problem, is I left out mentioning in my OnInit method I call the following code:
Dim cpl As ContentPlaceHolder = Master.FindControl("ContentPlaceHolderFooter")
btnUpdate = New Button
btn.ID = "btnUpdate"
cpl.Controls.Add(btnUpdate)
I know the purest will say why did you not add the button to the footer of the grid as opposed to an additional content placeholder in the master page - well with egg on my face I didn't.
Anyhow I moved the code above to the CreateChildControls overridable method and I also required an additional call to EnsureChildControls in my OnLoad event so my OnInit method with emphasis disintegrated!##%^* Why? Well the answer was hinted at within the answer to the other question asked on this site I mentioned in my second comment to "Rajan Chauhan" that I checked out and that is apparently whenever you iterate through the collection of controls you mess with the ViewState (hey I am just re-iterating what was said in the other post I have no authority on the matter) before it gets loaded so calling Master.FindControl is a no-no inside OnInit!
However, saying all that my RowUpdated event does not fire as I am actually editing in view mode because of my ItemTemplate markup so I will stick with what I have as my btnUpdate_Click event still works as before i.e. it does some magical code that I found on some other site that checks each row one by one for change of data and then updates that particular row only. Well I can as there is only 10 rows at most so I do not overload the ViewState too much and if it is important to know I also use paging so in reality I have more than 10 rows but did not want to mention that as I thought that might add to the confusion.

how to clear gridview without reloading the page

I have a gridview control on my asp.net page(vb.net). I also have a "cancel" button, that when pressed, is supposed to clear the gridview of it's current contents.
However whenever the cancel button is pressed, it just reloads the page and the gridview is still there with the same data that I wanted clear.
Based on suggestions that I found on stackoverflow, I set the datasource to nothing, but that is not working.
Here is my code for the cancel button:
Private Sub btnCancel_Click(sender As Object, e As System.EventArgs) Handles btnCancel.Click
gvQuizReport.DataSource = Nothing
gvQuizReport.DataBind()
End Sub
Any suggestions would be welcome!
Thanks
You might try:
gvQuizReport.Columns.Clear()
though as #Leniel Macaferi said, hiding the gridview is a possible solution as well.
since you have shown some interest in updatepanels, here is some starter code in case you are unfamiliar:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
If you already have a scriptmanager on your page you don't need to add another (you will get an error). if you have any problems implementing the updatepanel, feel free to post another question, there are plenty of people to help you with it
The code you showed should "clear" the results, but if you do not want anything displayed, you would hide the gridview by using gvQuizReport.Visible = False;
If you really want to clear without reloading the page, you could just use client side script to hide the grid object.
jquery hide

Multiline textbox - "Code blocks are not supported in this context"

I have a multiline (> 50 lines) textbox containing plain text. I want to add either a session variable to the text in this box. In asp I would have done it by putting in <% %> code blocks but in .net I am getting the following error: "Code blocks are not supported in this context". I assume therefore that this would need doing in code behind.
Is there a quicker way than putting all the text from the textbox in a string in code-behind and then adding the variable on like this? I would like to keep the text in my aspx page if possible.
Thanks
How about your codebehind does something like:
myTextbox.Text += Session ["mySessionVariable"];
after you've filled the textbox.
Incidentally, you don't have to
'put all the text from the textbox in
a string in codebehind'
as the .Net framework exposes all the front-end controls as codebehind objects automatically.
EDIT:
<asp:TextBox ID="TextBox1" runat="server" Rows="15" TextMode="MultiLine" Columns="70" Text='<%# Session["var1"] %>'></asp:TextBox>
This will work for binding just the session variable to the control. Don't forget to call
Page.DataBind();
after you've set your Session variables. Probably in Page_Load.
This will allow the binding such as it is, to occur. This won't work if you want to mix up static markup text with dynamic variables. For that, you'll need to get busy in the code-behind.
HTH.
Have you tried <%=Session["MySessionKey"] %> ?

Two-way data binding of controls in a user control nested inside a FormView doesn't work

I'm trying to perform two-way data binding on the controls in my user control, which is hosted inside a FormView template:
<asp:ObjectDataSource runat="server" ID="ObjectDataSource"
TypeName="WebApplication1.Data" SelectMethod="GetItem" UpdateMethod="UpdateItem">
</asp:ObjectDataSource>
<asp:FormView runat="server" ID="FormView" DataSourceID="ObjectDataSource">
<ItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</ItemTemplate>
<EditItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</EditItemTemplate>
</asp:FormView>
The web user control:
<%# Control Language="C#" ... %>
<asp:TextBox runat="server" ID="TitleTextBox" Text='<%# Bind("Title") %>'>
</asp:TextBox>
The binding works fine when the FormView is in View mode but when I switch to Edit mode, upon calling UpdateItem on the FormView, the bindings are lost. I know this because the FormView tries to call an update method on the ObjectDataSource that does not have an argument called 'Title'.
I tried to solve this by implementing IBindableTemplate to load the controls that are inside my user control, directly into the templates (as if I had entered them declaratively). However, when calling UpdateItem in edit mode, the container that gets passed into the ExtractValues method of the template, does not contain the TextBox anymore. It did in view mode!
I have found some questions on SO that relate to this problem but they are rather dated and they don't provide any answers that helped me solve this problem.
How do you think I could solve this problem? It seems to be such a simple requirement but apparently it's anything but that...
My current workaround for this is, although rather cumbersome, to subclass the FormView class and use subclassed controls in it, implementing my own data binding logic (taking the data field name from a new property) instead of using the <%# %> syntax. Apparently, the code the latter generates is the real culprit here as it doesn't support this nested control scenario.
I ended up, using old asp include statement
<--%include file = "filename" -->
instead of using user controls for dealing with the code duplication issue.

Paging Problems With Standard .net 2.0 Gridview using VB.Net

I am using a standart .net 2.0 Gridview which uses an XMLDatasource to populate the Grid. The Data property of the XMLDatasource is set dynamically which allows the gridview to change based on input.
All this works fine however I am having problems with paging...
I have set the AllowPaging Property to "true" and set the PageSize Property to "10". The GridView populates fine the first time around showing the first 10 records and the number of pages as hyperlinks at the bottom, BUT when i try to click on any of the page numbers to view them a message box pops up saying "Object reference not set to an instance of an object"
any ideas what I'm doing wrong?? or is there anything i need to do which i have missed out on??
Code currently being used;
Gridview...
<asp:GridView ID="GridView1"
Runat="server"
DataSourceID="XmlDataSource1"
AutoGenerateColumns="False"
AllowPaging="True"
style="width:100%; height:100%;"
EnableViewState="False">
<SelectedRowStyle BackColor="Red" />
<Columns>
<asp:BoundField DataField="TYPE" HeaderText="TYPE" SortExpression="TYPE" />
<asp:BoundField DataField="DESCRIPTION" HeaderText="DESCRIPTION" SortExpression="DESCRIPTION" />
</Columns>
</asp:GridView>
XMLDatasource...
<asp:XmlDataSource ID="XmlDataSource1" runat="server" TransformFile="~/XML/grid2.xslt" EnableCaching="False">
</asp:XmlDataSource>
vb.net code which sets the Data property of the XMLDatasource...
Private Sub btnTest_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnTest.Click
XmlDataSource1.Data = _testLib.GetGridXML(_Num)
GridView1.DataBind()
End Sub
where _testLib.GetGridXML is a function that returns an XML string based on the _Num passed in.
It's difficult to say without seeing your code... I would speculate that you assign the Data conditionally, i.e:
If Not IsPostBack Then
MyXMLDataSource.Data = "...some xml..."
End If
In this case it will be empty on post back and you get your exception. Could be something else, but then again, no code...
Update
Since you've added more information...
You must have something like code above on Page_Load. Since you are not providing it here, I presume you do. If you don't, you'd get the null reference exception on each load.
With that in mind, you assign data on some button click, but not on PageIndexChanging.
You click the button, the page loads, you assign the data, the grid shows it. Then you click the grid's next link, the page loads again, PageIndexChanging gets fired, your click event doesn't -- where's assignment then?
From what I see, either assign the Data property on Page_Load every time or do it in all subsequent events, i.e. on page change, on sort, etc.
Btw, you don't have to call DataBind when assigning XmlDataSource declaratively.
It should work if you do your databinding on the PreRender event
Since the XML datasource is being set dynamically if you set it on the PageLoad all the page elements might not exist at this stage.
Are you implelenting the OnPageChanging Event ? Normally you need to implement it and use the e.NewPageIndex property from the Event Argument to set it in your gridview.

Resources