What we want to do is save an entire control into Cache and recommit the properties on page load, including data items. But we'd like the controls to exist already in the page.
Is this possible?
<html>
<asp:Repeater runat="server" id="rptListOfSubscribers">
<ItemTemplate>
<%# Eval("Name")%><br />
</ItemTemplate>
</asp:Repeater>
</html>
VB:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If Cache("MyRepeater") Is Nothing Then
Dim rpt As Repeater = InitaliseRepeater()
Cache.Insert("MyRepeater"), rpt, Nothing, DateTime.Now.AddMinutes(720), Tim
eSpan.Zero)
End If
rptListOfSubscribers = Cache("MyRepeater")
End Sub
Function InitaliseRepeater() As Repeater
Dim rpt As New Repeater
rpt.DataSource = x
rpt.DataBind()
Return rpt
End Function
Excuse the short-hand code.
Yes that is possible the cache will take any object including a webcontrol. However probably best to do it earlier than Page_Load -Page_init perhaps.
Also I am curious as to your reasons behind doing this .. It seems like an awful solution. Also when you add the control to the page again when the viewstate page cycle methods run it will potentially change the control instance you have...
Can you describe the problem you are trying to solve with the cached web control?
Related
I wrote the below code which transfer the radio button value and check box value to another HTML form but i did not find solution to transfer the radio button or check box at all to another form not only the selected value.
I want the radio button to be transfered to another form as below not only the value.
enter image description here
Dim Gender As String = RadioButton1.SelectedValue
Response.Redirect("PrintPreview.aspx?"&Gender=" + Gender)
Label1.Text = Request.QueryString("Gender")
The code only returned the radio button value
Please advise
Ok, the FIRST thing, and MOST important thing to realize here is that when you execute a response.Redirect ?
It STOPS code running in the current page.
No code AFTER the Response.Redirect will run
All variables, and code and ALL values for the current page are destroyed!
So, you can't write (normally) code to run after the response.Redirect.
So, say we have this markup:
<br />
<asp:RadioButtonList ID="RadioButtonList1" runat="server"
Font-Size="Larger" RepeatDirection="Horizontal">
<asp:ListItem>Yes</asp:ListItem>
<asp:ListItem>No</asp:ListItem>
</asp:RadioButtonList>
<br />
<asp:Button ID="Button1" runat="server" Text="Done" />
And our page now looks like this:
Now, we want to jump to page 2.
So our code can say look like this in our Test1 page.
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Gender As String = RadioButtonList1.SelectedItem.Text
Response.Redirect("Test2.aspx?&Gender=" & Gender)
' code AFTER above line WILL NOT run!!!!
End Sub
So, we can't have code AFTER the response.Redirect.
Again, read this 5 times:
when the response.Redirect is used, then the current page code STOPS,
and ALL values, and even your code variables are DESTROYED!!! This is not much
different then when you get to the end of a subroutine - when you exit, then all
values and things in that subroutine are "gone", and "do not exist".
The same goes for your web page - using Response.Redirect means STOP code, transfer to another page.
So, now above will jump to page Test2, we want to take that value we passed, and do this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' save a label on this page to the passed choice
Label1.Text = Request.QueryString("Gender")
End If
End Sub
Also, note close your syntax for the string you were passing in Response.Redirect was also incorrect.
Lately i realized a problem in asp.net, which appears kinda strange to me.
I got an sample.aspx file:
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="sample.aspx.vb" Inherits="SampleProj.sample" MasterPageFile="~/Site.Master" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<input type="image" id="Accept" runat="server" class="accept-btn" src="/Images/accept.png" />
</asp:Content>
And the related codebehind file sample.aspx.vb:
Public Class sample
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Some code here
End Sub
Private Sub Accept_ServerClick(sender As Object, e As ImageClickEventArgs) Handles Accept.ServerClick
'Some code here
End Sub
So my Problem is easily explained: Upon clicking the accept button the Accept.ServerClick event is fired as expected, but for some reason (even though the page IS NOT reloaded) the Page.Load event is fired too. This is my first asp project and maybe this is an expected behaviour, but i found neither an explanation nor a way to disable it. Any information would be appreciated.
Greeting, Ohemgi
(If you find any errors this is caused by writing this short sample. My code is compiling and running without a problem, so my question is only about the load event)
That is perfectly fine. From MSDN Documentation:
After a page has been posted back, the page's initialization events (Page_Init and Page_Load) are raised, and then control events are processed.
If you do something in the Page_Load that you don't want to do every time you click a button, just wrap it inside this condition:
if (!Page.IsPostBack)
{
// Some code here. It is executed only once.
}
You can find more information in the links below:
ASP.NET Web Server Control Event Model
ASP.NET Page Life Cycle Overview
VB.Net version
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
' Some code here. It is executed only once.
End If
End Sub
I'm using the FindControl function to look for a control on the page. It seems super simple and straight forward on MSDN but I can't get it to find the control. The page I'm using has a MasterPageFile that prepends more to the id that I give the contorl in the aspx file. A simple example that isn't working:
aspx page
<%# Page Title="Inventory Control Test" Language="VB" AutoEventWireup="false" MasterPageFile="~/Site.master" CodeFile="Default2.aspx.vb" Inherits="Sales_ajaxTest_Default2" %>
<asp:Content ID="conHead" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="conBody" ContentPlaceHolderID="MainBody" Runat="Server">
<asp:Button ID="saveAllBtn" runat="server" Text="Save All" />
</asp:Content>
code behind
Partial Class Sales_ajaxTest_Default2
Inherits System.Web.UI.Page
Protected Sub saveAllBtn_Click(sender As Object, e As System.EventArgs) Handles saveAllBtn.Click
Dim myControl1 As Control = FindControl("ctl00_MainBody_saveAllBtn")
If (Not myControl1 Is Nothing) Then
MsgBox("Control ID is : " & myControl1.ID)
Else
'Response.Write("Control not found.....")
MsgBox("Control not found.....")
End If
End Sub
End Class
I get that msgbox isn't a web thing I'm just using it for this example.
If i use "saveAllBtn", which is the id given to the control, in the FindControl I get "control not found". If I try this, on a stand alone page without a masterpage it works fine.
If I inspect the element using chrome I find that the ID of the button has been changed to "ctl00_MainBody_saveAllBtn" but if I use that in the FindControl I still get "control not found"
When you use FindControl you would specify the "server ID" (what you named it) of the control, not the final rendered "client ID" of the control. ex:
Dim myControl as Control = MainBody.FindControl("saveAllBtn")
However, in your specific example, since you are in the saveAllBtn.Click event, the control you are looking for is actually the sender parameter (because you clicked on that button to trigger the event you are in) ex:
Dim myControl as Button = CType(sender, Button)
If you just want to find saveAllBtn control, wweicker's second method using CType(sender, Button) is the prefer one.
However, if you want to find other control by name, you cannot use just FindControl. You need to find the control recursively, because it is nested inside other controls.
Here is the helper method -
Protected Sub saveAllBtn_Click(sender As Object, e As EventArgs)
Dim button = TryCast(FindControlRecursive(Me.Page, "saveAllBtn"), Button)
End Sub
Public Shared Function FindControlRecursive(root As Control, id As String) As Control
If root.ID = id Then
Return root
End If
Return root.Controls.Cast(Of Control)().[Select](Function(c) FindControlRecursive(c, id)).FirstOrDefault(Function(c) c IsNot Nothing)
End Function
Note: My VB code might be a bite weird, because I wrote in C# and converted to VB using converter.
FindControl does not work recursively. You must start at one point (Me, for example), and if that is not the control your looking for, search the Controls collection of your starting point. And so forth.
I have a VB ASP.NET web application with two User Controls each containing one text input. There are two submit buttons each corresponding to one of the User Controls.
Clicking a button adds an instance of its corresponding User Control. For the most part this works except that in a specific scenario the IDs of the textboxes get mixed up thereby mixing up previously entered values.
The problem scenario is as follows:
1) Click the second button (the Add Approver button) twice and enter some values in the two resulting textboxes (for ease of analysis make the values different).
2) Click the first button (the Add Document button) once. (There is no need to add any value in the resulting textbox here.)
At this point everything appears correct. Viewing the page source, I see that the two "Approver" textboxes have IDs of ctl02_txtApprover and ctl03_txtApprover and the one "Document" textbox has an ID of ctl04_txtDocument.
Click the first button (the Add Document button) again.
At this point the value in the first "Approver" textbox disappears. The value in the second "Approver" textbox migrates to the first "Approver" textbox. Viewing the page source, the IDs for the two "Approver" textboxes have changed to ctl03_txtApprover and ctl04_txtApprover. The migrated values make sense considering that the textbox IDs have changed. In other words, the ViewState appears correct but the control IDs are incorrect.
I have made the code as simple as I can and have posted it here.
Default.aspx
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="WebApplicationUserControlTest._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:PlaceHolder ID="phDocument" runat="server" />
<asp:Button ID="btnAddDocument" runat="server" Text="Add Document" />
<br /><br />
<asp:PlaceHolder ID="phApprover" runat="server" />
<asp:Button ID="btnAddApprover" runat="server" Text="Add Approver" />
</form>
</body>
</html>
Default.aspx.vb
Public Class _Default
Inherits System.Web.UI.Page
Private Const VIEWSTATE_DOCUMENT_COUNT As String = "DocumentCount"
Private Const VIEWSTATE_APPROVER_COUNT As String = "ApproverCount"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ViewState(VIEWSTATE_DOCUMENT_COUNT) = 0
ViewState(VIEWSTATE_APPROVER_COUNT) = 0
Else
're-display any preexisting dynamic sections on postback
AddAllDocumentInfoSections()
AddAllApproverSections()
End If
End Sub
Protected Sub btnAddDocument_Click(sender As Object, e As EventArgs) Handles btnAddDocument.Click
ViewState(VIEWSTATE_DOCUMENT_COUNT) += 1
AddDocumentSection()
End Sub
Protected Sub btnAddApprover_Click(sender As Object, e As EventArgs) Handles btnAddApprover.Click
ViewState(VIEWSTATE_APPROVER_COUNT) += 1
AddApproverSection()
End Sub
Private Sub AddAllDocumentInfoSections()
For i As Integer = 0 To ViewState(VIEWSTATE_DOCUMENT_COUNT) - 1
AddDocumentSection()
Next
End Sub
Private Sub AddAllApproverSections()
For i As Integer = 0 To ViewState(VIEWSTATE_APPROVER_COUNT) - 1
AddApproverSection()
Next
End Sub
Private Sub AddDocumentSection()
Dim c As UserControl = LoadControl("~/Document.ascx")
phDocument.Controls.Add(c)
End Sub
Private Sub AddApproverSection()
Dim c As UserControl = LoadControl("~/Approver.ascx")
phApprover.Controls.Add(c)
End Sub
End Class
Document.ascx
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="Document.ascx.vb" Inherits="WebApplicationUserControlTest.Document" %><asp:TextBox ID="txtDocument" runat="server" /><br /><br />
Approver.ascx
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="Approver.ascx.vb" Inherits="WebApplicationUserControlTest.Approver" %><asp:TextBox ID="txtApprover" runat="server" /><br /><br />
I am using Visual Studio 2010. The Target Framework is 4.0. I have tried changing the clientIDMode but this does not seem to make a difference. Have I run into a bug with .NET or is there something wrong with my code?
There is something wrong with your code.
If you dynamically add controls to the same naming container in a control tree, then you need to add them in the same order after each postback.
In your case, you're not doing this.
At your step 2, you have added three controls in this order:
Approver 1 (AddAllApproverSections)
Approver 2 (AddAllApproverSections)
DocumentInfo 1 (btnAddDocument_Click)
But then after the postback, you regenerate them in the following order:
DocumentInfo 1 (AddAllDocumentInfoSections)
Approver 1 (AddAllApproverSections)
Approver 2 (AddAllApproverSections)
Hence the control ids aren't the same, and the problems you're seeing.
One solution might be to store additional information in ViewState that represents the order the controls were added, so that you can recreate them in the same order.
But I'd probably be inclined to go for a different approach, for example put the DocumentInfo sections into the template of a Repeater, and the Approver sections into a second Repeater. Each Repeater would be data bound to a suitable collection, and adding an item (Approver or DocumentInfo) would be achieved by adding an element to the relevant collection and calling DataBind.
The problem here is that you are modifying the Controls collection and ViewState after they have been initialized. You should never dynamically add controls in the Page Load event.
You need to add your controls in the Page_Init stage of the Page life cycle, and remove the code from the else statement in your Page_Load event. Your new Page_Init event would look like this:
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
AddAllDocumentInfoSections()
AddAllApproverSections()
End Sub
I believe you may have to change the way you're storing the "count" for these controls, as the View State information is not yet available at this stage. I would just store it as a Session variable, in that case. You'd just need to change your reference to "ViewState" throughout that code sample with "Session", like this:
Private Sub AddAllDocumentInfoSections()
For i As Integer = 0 To Session(VIEWSTATE_DOCUMENT_COUNT) - 1
AddDocumentSection()
Next
End Sub
How do I set ListView data through the codebehind instead of using the Bind() function in the Text attribute?
Right now I'm doing the following, but I'd like to have it retrieved and set in the codebehind. I'm using VB... Thanks!
<asp:Label ID="Date" runat="server" Text='<%# Bind("Date") %>'></asp:Label>
Edit:
Sorry, I'm binding the data in the following way with a DataTable.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ListView.DataSource = MyDataTable
ListView.DataBind()
End If
End Sub
use the ItemDataBound event.
Without seeing your code, I can tell you that a ListView has a DataSource property that you should just be able to set in your load code (and then do a DataBind()). I know I've done that before with a GridView.
Based on the info you have provided this is the best I can give you. You may want to put this snippet in the PreRender event for your ListView.
Label lblDate = (Label)ListView.FindControl("Date");
if(dataTable.Rows.Count > 0 && dataTables.Columns.Contains("Date"))
{
DataRow row = dataTable.Rows[0];
If(!DBNull.Equals(row["Date"])
{
lblDate.Text = row["Date"].ToString();
}
}