method firing twice during pageload in asp.net - c#

I know such questions are asked already on SO, and i also went through most of them but no one satisfied me, so i am posting mine one. Attached is my code. actually i am building a jquery gallery from code from databale. see the code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DisplayHotProducts();
}
}
private void DisplayHotProducts()
{
var dt = ProductData.GetAllHotProducsts();
if (dt != null && dt.Rows.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(" <div id='spotlight_products' class='widget_box center_box'>");
sb.AppendLine("<div class='wintitle'>");
sb.AppendLine(" <div class='inner_wintitle'>");
sb.AppendLine(" Hot Products</div></div>");
sb.AppendLine("<div class='winbody'>");
sb.AppendLine("<div class='mall_focus' id='mall_focus'>");
sb.AppendLine("<a id='bp_carousel_prev'>prev</a>");
sb.AppendLine("<a id='bp_carousel_next'>next</a>");
sb.AppendLine("<div id='bp_carousel'>");
sb.AppendLine(" <div class='carousel_list'>");
for (int i = 0; i < dt.Rows.Count; i=i+5)
{
sb.AppendLine(" <div class='product_list'>");
sb.AppendLine("<div class='bestproduct_wrapper'> <div class='bestproduct'>");
sb.AppendLine(" <div class='icon_best'></div>");
sb.AppendLine("<ul>");
sb.AppendLine(" <li class='best_Img'><span></span><a href='#' target='_blank'> ");
sb.AppendLine(string.Format(" <img src='{0}' width='200' height='200' /></a></li>", dt.Rows[i]["ImagePath"]));
sb.AppendLine("</ul>");
sb.AppendLine(" <p class='product_name'>");
sb.AppendLine(string.Format("<a href='Products/{0}' target='_blank'>{1}</a></p>", dt.Rows[i]["Id"], dt.Rows[i]["Name"]));
sb.AppendLine("</div></div>");
for (int j = i+1; j <= 4; j++)
{
sb.AppendLine("<div class='product_item'>");
sb.AppendLine("<ul><li class='product_Img'>");
sb.AppendLine(string.Format("<a href='Products/{0}'><img src='{1}' width='70' height='70'/></a>", dt.Rows[j]["Id"], dt.Rows[j]["ImagePath"]));
sb.AppendLine("</li></ul>");
sb.AppendLine(string.Format("<p class='product_name'><a href='Products/{0}'>{1}</a></p>", dt.Rows[j]["Id"], dt.Rows[j]["Name"]));
sb.AppendLine("</div>");
}
}
sb.AppendLine(#" </div></div></div></div></div>");
ltlHotProducts.Text = sb.ToString();
}
}
}
My code behind has the above code only and the page load is firing twice.
Also this is code behind of a usercontrol, placed on a page where i have 3 more similar control performing similar functionalities that is , building jquery slideshows from code behind. But the above two user controls has some issues with the img tags as some of them are missing images. Also the page on which the user controls are placed has a master page. Now please suggest me the solution.
So the heirarchy is something like this:
Master Page (master) -> Content Page (aspx) -> Has->3 UserControls (ascx)

I have typically seen two reasons for the PageLoad to fire twice - First, if you have an img tag that doesn't have a src attribute, IE and Chrome will both request the page again, which causes the event to fire again. Second, if the event is wired up more than once, it'll fire more than once; Typically I've seen this happen when the code behind includes the event wireup code (eg, this.PageLoad += ... PageLoad) and the page directive AutoEventWireup=True is included in the aspx file.

Related

Dynamically add div in .aspx page

I'm looking for a JavaScript-free way to dynamically add div elements inside a certain element of an aspx web page according to data passed to i.
I'm looking for something similar to razor c# where you can even create loops and write c# code that directly effects the content of the page.
It appears that razor c# doesn't work unless the page is a .cshtml page, so I'm kinda lost here since I don't want to use JavaScript.
Is there a better approach to it?
Say, below is the placeholder div
<div id = "maindiv">
<asp:PlaceHolder ID ="maindivs" runat="server">
</asp:PlaceHolder>
</div>
Then you may add divs to your placeholder div like below
protected void addmainDiv(int m)
{
for(int i = 0; i< m; i++)
{
System.Web.UI.HtmlControls.HtmlGenericControl newdivs = new System.Web.UI.HtmlControls.HtmlGenericControl("DIV");
newdivs.Attributes.Add("class", "maindivs");
newdivs.ID = "createDiv";
newdivs.InnerHtml = " I'm a div, from code behind ";
maindivs.Controls.Add(newdivs);
}
}
If you want to create HTML dynamically in .aspx then you can create your html code in your .cs (backend file)
string htmlAsStringToShow = "<div>" + variable + "</div>";
Then show its content in your .aspx page like this :
<%= htmlAsStringToShow %>

How to store/restore table with dynamic elements in view state in c# asp web aplication

I am new to concept of web app with dynamic content.
I am creating simple app that take information (steps for a test) from database and adds rows to table (every row is containing, two labels, two radio buttons and text field).
It works like this:
1. I have a page with text box and button,
2. I put test ID to retrieve test steps, then click submit button
3. Based on number of steps I add a row to table for every step, so I have table that looks like this:
[Label.text="Step1"][RadioButtonPass][RadioButtonFail][Label.Text="Comment:"][TextBox]
[Label.text="Step2"][RadioButtonPass][RadioButtonFail][Label.Text="Comment:"][TextBox]
[Label.text="Step3"][RadioButtonPass][RadioButtonFail][Label.Text="Comment:"][TextBox]
etc.
When user press every radio button he can click submitResult button and data are send to db.
Page is genereting correctly but I am having trouble with dynamic content because when I hit submitResult button table is empty again (at this point submitResult button do nothing). I read about it and I think I need to store table into View State. How can I do it?
I tried to save table to
ViewState[table.ID] = table;
at the end of PopulateTable method and then restore it in
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if (ViewState[TableForMethods.ID] != null)
{
TableForMethods = (Table)ViewState[TableForMethods.ID];
}
}
}
but that doesn't work.
My code looks like this:
*.aspx
<body style="height: 510px">
<form id="form1" runat="server">
<p>
Put test case ID and submit
</p>
<asp:TextBox ID="TextBoxId" runat="server">1804673290</asp:TextBox>
<asp:Button ID="ButtonRetriveId" runat="server" OnClick="ButtonSubmitId_Click" Text="Submit" Width="81px" />
<p>
</p>
<p>
<asp:Label ID="LabelMethods" runat="server"></asp:Label>
</p>
<p>
<asp:Table ID="TableForMethods" runat="server">
</asp:Table>
</p>
<div style="text-align: right">
<asp:Button ID="ButtonSubmitResults" runat="server" Text="Submit result" OnClick="ButtonSubmitResults_Click" Visible="False" />
</div>
<div style="text-align: right; position: absolute; bottom: 0px">
<asp:Label ID="LabelStatus" runat="server"></asp:Label>
</div>
</form>
<script>
var trPassArray = $("tr input[id*='RadioButtonPass']").click(function () {
this.closest("tr").setAttribute("bgcolor", "yellowgreen");
console.log("zmien na green");
console.log(closest("tr"));
});
var trFailArray = $("tr input[id*='RadioButtonFail']").click(function() {
this.closest("tr").setAttribute("bgcolor", "orangered");
console.log("zmien na red");
console.log(this.closest("tr"));
});
console.log(trPassArray);
console.log(trFailArray);
</script>
</body>
*.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ButtonSubmitId_Click(object sender, EventArgs e)
{
this.PopulateTable(TableForMethods, value);
ButtonSubmitResults.Visible = true;
}
protected void ButtonSubmitResults_Click(object sender, EventArgs e)
{
}
private void PopulateTable(Table table, string value)
{
string[] sep = { "<br>" };
var words = value.Split(sep, StringSplitOptions.RemoveEmptyEntries);
for (int iterator = 1; iterator <= words.Count(); iterator++)
{
var tRow = new TableRow { ID = "Row" + iterator };
table.Rows.Add(tRow);
var tCell = new TableCell();
var myLabel = new Label
{
Text = words[iterator - 1],
ID = "Label " + iterator
};
var radiobuttonPass = new RadioButton
{
Text = "Pass ",
ID = "RadioButtonPass " + iterator,
GroupName = "passFailGroup" + iterator,
};
radiobuttonPass.CheckedChanged += passRadioButton_CheckedChanged;
var radiobuttonFail = new RadioButton
{
Text = "Fail ",
ID = "RadioButtonFail " + iterator,
GroupName = "passFailGroup" + iterator,
};
radiobuttonFail.CheckedChanged += failRadioButton_CheckedChanged;
var upPassFail = new UpdatePanel { UpdateMode = UpdatePanelUpdateMode.Conditional };
upPassFail.ContentTemplateContainer.Controls.Add(radiobuttonPass);
upPassFail.ContentTemplateContainer.Controls.Add(radiobuttonFail);
var passTrigger = new AsyncPostBackTrigger
{
ControlID = radiobuttonPass.ID,
EventName = "CheckedChanged"
};
upPassFail.Triggers.Add(passTrigger);
var failTrigger = new AsyncPostBackTrigger
{
ControlID = radiobuttonFail.ID,
EventName = "CheckedChanged"
};
upPassFail.Triggers.Add(failTrigger);
var labelComment = new Label
{
Text = " Comment:",
ID = "LabelComment " + iterator.ToString()
};
TextBox textBoxComment = new TextBox { ID = "TextBoxComment " + iterator.ToString() };
tCell.Controls.Add(myLabel);
tCell.Controls.Add(radiobuttonPass);
tCell.Controls.Add(radiobuttonFail);
tCell.Controls.Add(labelComment);
tCell.Controls.Add(textBoxComment);
tRow.Cells.Add(tCell);
}
}
What you're trying to do won't work. ViewState is used by the server application to store information between requests.
During the course of page load or a postback the server modifies the state of the page or its controls
When you post back, without some way to "remember" what was done, all of those changes would be lost. It would be like loading the page for the first time again.
ASP.NET solves this by writing details about the controls in a form field (ViewState.) That way every time there's postback you're sending data back to the server telling it what the state of the page and controls are, so it can recreate it.
You're making changes to the HTML on the client. At that point the page has been rendered, including ViewState. It only keeps track of the server's changes, not anything that happens on the client. So the server will never know that those changes happened.
There are a few ways to solve this (more than two, but these are the obvious ones.)
Whatever changes have to happen to modify that table, do it on the server. If the user interacts with something, do a postback to the server. The server modifies the table, and assuming that ViewState is enabled for the table, those changes are already written to ViewState and persisted.
Avoid postbacks. If there aren't server controls then after the page loads it behaves just like a normal HTML page, and you can do whatever you want on the client.
This gets a little messy: store client-side changes on the client. When you update the table on the client then you could store it in localStorage. When the page refreshes you could then have a client script that checks localStorage and restores whatever client-side stuff you stored there. Think of it as just like ViewState, but the opposite. ViewState stores server-side data between roundtrips. localStorage stores client-side data between roundtrips. The catch is that maybe on some postback you'll completely change the table (like new data, something else) and you'll have to have a way to distinguish that so that in that scenario you don't refresh it from localStorage.
Mixing WebForms with client-side code can be a little frustrating. We start learning about all of these neat client-side tools, but they don't always play well with the behavior of WebForms. Client-side code wants to change things on the page. WebForms wants to refresh the whole page.
Personally I would go with option one or two if possible vs trying to cross-breed the behavior of the two.

How to get the html code modified client side that was generated from the server side?

I created a list with jquery sortable + C#, that the user (client) can order:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
HtmlGenericControl ul = new HtmlGenericControl("ul");
ul.ID = "ID";
ul.ClientIdMode = Static;
HtmlGenericControl li_1 = new HtmlGenericControl("li");
li_1.ID = "segment";
li_1.InnerText = "server 1";
li_1.ClientIdMode = Static;
HtmlGenericControl li_2 = new HtmlGenericControl("li");
li_2.ID = "page";
li_2.InnerText = "server 1";
li_2.ClientIdMode = Static;
ul.Controls.Add(li_1);
ul.Controls.Add(li_2);
static.Controls.Add(ul);
}
Server Generate:
<div id="static" runat="server">
<ul id="ID">
<li id="segment">server 1</li>
<li id="page">server 2</li>
</ul>
</div>
Client Generate (modified):
<div id="static" runat="server">
<ul id="ID">
<li id="page">client 1</li>
<li id="segment">client 2</li>
</ul>
</div>
Event Save:
protected void btnSave_Click(object sender, EventArgs e)
{
HtmlGenericControl ul = Libreria.Global.FindControlRecursivo(this, "ID") as HtmlGenericControl;
foreach(HtmlGenericControl li in ul.Controls.OfType<HtmlGenericControl>())
{
// Always get html generated by server, first "segment" element and after "page" element
}
}
If every time I generate dynamic code on every postback I always get the code that the server generates, if valid then the lists are empty postback. =(
How do I get the html code modified client side that was generated from the server side?
Update:
other option is using WebMethods
with javascript send the html:
document.getElementById("ID").innerHTML;
I CanĀ“t process the elements is a simple string
HtmlGenericControl ul = new HtmlGenericControl();
ul.InnerHtml = stringHtml;
foreach(HtmlGenericControl li in ul.Controls.OfType<HtmlGenericControl>())
{
// any element
}
more read about. what is server control.
asp.net manage their control in viewstate and here in your scenario you are creating control on client side using jquery and send it's inner Html as string to the server side.. which is treated as string on server side is true.
you can do one thing to maintain this. just use ajax and add item to your "static" div on server side and it will be render on client side. cause of partial post back it won't take time. and look like your are creating it client side.
I solved the problem with an object in javascript, the user changes the elements (li) and to do click save final order of the elements and sends calling one webmethod working with this array type object

How to create an array of User Controls programmatically

How do I programmatically create an array of web user controls?
I created a web user control. I already know how to implement one of them coding in the aspx file, however I would like to know if it is possible to do that from the code behind in either the Page_Init() or the Page_Load() event.
I already know the initialization on the aspx page.
<%# Register TagPrefix="uc" TagName="myUsercontrol1" Src="/Controls/myUsercontrol1.ascx" %>
In the traditional way, I would do something like:
<div id="divMyusercontrols" runat="server">
<uc:myUsercontrol1 id="ctlTheControl" runat="server" />
</div>
What I was wanting to do, which does not work, as I tried, is:
In the aspx file:
<div id="divMyusercontrols" runat="server">
</div>
In the code behind in let us say the Page_Init() event the following:
String strControl = "<uc:myUsercontrol1 id="ctlTheControl{0}" runat="server" />";
String strHtml = null;
for (int i = 0; i < 5; i++)
strHtml += String.Format(strControl, i.ToString());
this.divMyusercontrols.InnerHTML = strHtml;
This code sadly does not work. I realize that I can simply do that manually, but I do not know the actual count. I will know that ahead of time.
UPDATE (to show answer #3 proper code):
The C# for the aspx file is the following. I have a call to a static C# code behind, which returns the count. I then set a property to indicate which item to show and then the for-loop. Cool!
<%int iCount = MyProject.Items;%>
<%for (int iIndex = 0; iIndex < iCount; iIndex++)%>
<%{ %>
<div runat="server">
<uc:myUsercontrol1 id="ctlItem<%=iIndex %>" runat="server" />
</div>
<%}%>
SOLUTION (2013-02-12):
I tried out all three answers below, sadly after I marked one as a solution. The winning one is a modified version of the Page_LoadControl(). Here is the code that works, and yes, I ran the code. Everything works.
// Load an array of controls onto a predefined panel.
for (int iIndex = 0; iIndex < 10; iIndex++)
{
// Load the control.
MyProject.Controls.MyControl ctlItem = (MyProject.Controls.MyControl)Page.LoadControl(#"/Controls/MyControl.ascx");
// Initialize the control.
ctlItem.MyIndex = iIndex;
// Add the control to the panel.
this.pnlItems.Controls.Add(ctlItem);
}
Here is the fixed aspx code.
<div id="divItems" runat="server" class="divItems">
<dx:ASPxPanel ID="pnlItems" runat="server" Width="200px">
</dx:ASPxPanel>
</div>
I tried doing, MyProject.Controls.MyControl ctlItem = new MyProject.Controls.MyControl(), however that does not work. I got a null excemption. Loading the control worked.
The answer, which I too hastilly marked as a solution, does not work. When ran the designer complained. Here is the code from the designer.
/// <summary>
/// ctlPurchases<%=iIndex %> control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::MyProject.Controls.MyControl ctlItem<%=iIndex %>;
The designer was unhappy about the <%...%> part. This solution has other problems. The cleanest one is using the Page_LoadControl.
Can you use an ASP.NET Panel and use Page.LoadControl()?
for (int i = 0; i < 10; i++)
{
pnlContent.Controls.Add(Page.LoadControl("ucDemo.ascx"));
}
This is in C# BTW.
Or if these UserControls will be data bound, you could try using a Repeater control.
When I want multiple copies of my user control I usually follow the pattern below
<%for (Counta = 1; Counta <= 10; Counta++) {%>
<div id="divMyusercontrols<%=Counta%>" runat="server">
<uc:myUsercontrol1 id="ctlTheControl<%=Counta%>" runat="server" />
</div>
<%}%>
The code above would give me 10 UserControls nested inside 10 div elements
UPDATE
Please note that I have used an on-line tool to convert the code from VB to c# So how accurate it is I don't know. Yet I don know it works for me in VB.
The VB Code is below for comparison
<%for Counta = 1 To 10%>
<div id="divMyusercontrols<%=Counta%>" runat="server">
<uc:myUsercontrol1 id="ctlTheControl<%=Counta%>" runat="server" />
</div>
<%Next%>
I think you can do in Page_Load:
HtmlGenericControl control = FindControl("divMyusercontrols")
var myControl = new MyControl();
for(int i=0; i<numberOfUserControls; i++)
{
myControl.ID = "myUniqueID" + i;
}
myControl.Controls.Add(myControl);

Variable does not exist in the current context

I'm new to C# .NET. I would like to ask how this works... What I want is just to show an age selection from 1 to 100.
Inside the .aspx file I put this code, I used data binding for the variable listAge.
<asp:DropDownList ID="AgeDropDown" runat="server">
<%# listAge %>
</asp:DropDownList>
Here's the code-behind for it:
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 1; i < 101; i++)
{
string listAge;
listAge = "<asp:ListItem>"+ i +"</asp:ListItem>";
}
}
The error shown inside the .aspx is:
Error Creating Control: AgeDropDown - Code blocks are not supported in this context.
Because of the variable listAge?
Thank you for the help!
Drop the <% %> section in .aspx and in code behind you should do something like this:
protected void Page_Load(object sender, EventArgs e)
{
AgeDropDown.Items.Clear();
for (int i = 1; i < 101; i++)
{
AgeDropDown.Items.Add(new ListItem(i.ToString(),i.ToString()));
}
}
From another point of view there are several flaws in your code:
You are generating ASP.NET tags in code behind. ASP tags are processed on the server and are rendered into html tags. You were practically inserting a tag in html, which browsers will render as simple text since it's not a valid HTML tag.
You were creating a new listAge variable on each iteration of the for loop. Even if the code would work it would display just the last item
You could use the server version of AgeDropDown.
ListItem li;
for (int i = 1; i < 101; i++)
{
li = new ListItem(i.ToString(), i.ToString());
AgeDropDown.Items.Add(li);
}
Is this in asp.net or MVC?
Probably
... <%# listAge %>
should be
... <%= listAge %>

Categories