I am very new to ASP.NET but I have background in C and C#. I am trying to make web application which will be connected with my database. I did that and that is OK. The problem occurred when I added buttons for moving forward and backward through the database... It was working fine but only for one click! Then I thought that probably I have bug in the code and I decided to do it in easy way.
I created new web form with just one button and one label, but behavior is still the same- after first click event is not fired again. Any help?
My code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DummyTest
{
public partial class WebForm1 : System.Web.UI.Page
{
int pom = 0;
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = Convert.ToString(pom);
}
protected void Button1_Click(object sender, EventArgs e)
{
pom++;
Label1.Text = Convert.ToString(pom);
}
}
}
and source
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="DummyTest.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
Dummy Test
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
</div>
</form>
</body>
Your Webform class gets recreated on every request - that's just how it works. You need to persist the field pom in some other way. You could add it to the session state, but that affects scalability of the application as you then hold state on the server.
It is already persisted by the label control, so you could do something like this in your click event:
var pom = Int.Parse(Label1.Text);
pom++;
Label1.Text = pom.ToString();
However, this will not always be the case for something you want to persist. In these cases I would add a hidden field to the html which holds it. My WebForms is a little rusty, but in your markup:
<asp:HiddenField id="pom" value="0" />
then pull the value out and increment in the click event as I've done above.
Whenever you click your int pom = 0 get initialized to zero and then you set value that is why it looks it calling once. either make it static or better to try:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "" + (Convert.ToInt32(Label1.Text) + 1);
}
You could try moving your initialisation into an IsPostBack check, so reloading the page does not re-intitialise the variable to 0. The IsPostBack value indicates whether the page is being rendered for the first time or is being loaded in response to a postback and a button click event triggers a postback.
Additional
The IsPostBack fires at a specific stage in the page lifecycle
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int pom = 0;
}
Label1.Text = Convert.ToString(pom);
}
To some extent it depends what the purpose of the pom variable is. If it is tracking clicks per user then the above should help. However if you're tracking clicks across all users then you should consider something else (probably using the global.asax)
It is working now! Here is code for Up and Down.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DummyTest
{
public partial class WebForm1 : System.Web.UI.Page
{
static int pom;
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
{
pom = 0;
Label1.Text = Convert.ToString(pom);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
var pom = Int32.Parse(Label1.Text);
pom++;
Label1.Text = Convert.ToString(pom);
}
protected void Button2_Click(object sender, EventArgs e)
{
var pom = Int32.Parse(Label1.Text);
pom--;
Label1.Text = Convert.ToString(pom);
}
}
}
Related
I'm trying to generate a user control, which consists of a label, dropdown menu, and text box, dynamically so I can set the value of the label. When I run it, I have an issue with the dropdown and textbox because they need to be in a form tag with runat server. When I add the form tag, the compiler complains that there can only be one form tag. Please help. This is my code:
User Control:
<%# Control Language="C#" AutoEventWireup="true"
CodeFile="IngredientQuantityControl.ascx.cs" Inherits="IngredientQuantityControl" %>
<asp:Label ID="IngredientDisplay" runat="server" Text="Label"></asp:Label>
<asp:DropDownList ID="DropDownList1" runat="server" >
<asp:ListItem Value=null >Please Choose a Unit</asp:ListItem>
<asp:ListItem Value="Unit">Unit(s)</asp:ListItem>
<asp:ListItem>Cup</asp:ListItem>
<asp:ListItem>Tbsp</asp:ListItem>
<asp:ListItem>Tsp</asp:ListItem>
<asp:ListItem>To Taste</asp:ListItem>
<asp:ListItem>Milligrams</asp:ListItem>
</asp:DropDownList>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
CodeBehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class IngredientQuantityControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void SetLabelText(String s)
{
IngredientDisplay.Text = s;
}
}
Dynamically Adding to the panel
protected void Button1_Click(object sender, EventArgs e)
{
Page.Controls.Add(LoadControl("IngredientQuantityControl.ascx"));
IngredientQuantityControl uc = (IngredientQuantityControl)Page.LoadControl("IngredientQuantityControl.ascx");
uc.SetLabelText("Halleluyah!");
Panel1.Controls.Add(uc);
//string text = listBox1.GetItemText(listBox1.SelectedItem);
}
}
You are adding the IngredientQuantityControl.ascx as control twice.
protected void Button1_Click(object sender, EventArgs e)
{
IngredientQuantityControl uc = (IngredientQuantityControl)Page.LoadControl("IngredientQuantityControl.ascx");
uc.SetLabelText("Halleluyah!");
Panel1.Controls.Add(uc);
//string text = listBox1.GetItemText(listBox1.SelectedItem);
}
I've created a very simple bit of code in C# to display data in an asp:Table. On the initial page load all looks great. I've used an AJAX timer to refresh every 15 seconds to keep the data up to date. The problem is after it refreshes the table shows all the data duplicated. I've tried debugging and again all looks good until the AJAX refresh and then it seems to jump all over the place in the C# code rather than following the expected sequence.
Hopefully I've not approached this in completely the wrong way but if I have please tell me! Is there a way to prevent/fix this duplication?
I've replicated the problem code here in a very simple form. Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="testASPTables._default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:Table ID="Table1" runat="server">
</asp:Table>
<asp:Timer ID="Timer1" runat="server" Interval="15000" OnTick="Timer1_Tick">
</asp:Timer>
</div>
</form>
</body>
</html>
...and the codebehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace testASPTables
{
public partial class _default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TableRow[] tRows = new TableRow[5];
TableCell[] tCells = new TableCell[5];
for (int i = 0; i < 5; i++)
{
tRows[i] = new TableRow();
Table1.Rows.Add(tRows[i]);
tCells[i] = new TableCell();
tRows[i].Cells.Add(tCells[i]);
tCells[i].Text = "Cell Number: " + i.ToString();
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
Page_Load(sender, e);
}
}
}
You're calling Page_Load twice. Page_Load runs on postback, then you call it again from Timer1_Click.
You need to always be concious of whether the page is in a postback or not and how Page_Load works.
Here's what I'd do.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
LoadTableData();
}
}
protected void LoadTableData()
{
Table1.Rows.Clear(); //I added this
TableRow[] tRows = new TableRow[5];
TableCell[] tCells = new TableCell[5];
for (int i = 0; i < 5; i++)
{
tRows[i] = new TableRow();
Table1.Rows.Add(tRows[i]);
tCells[i] = new TableCell();
tRows[i].Cells.Add(tCells[i]);
tCells[i].Text = "Cell Number: " + i.ToString();
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
LoadTableData();
}
Oh, and in addition to that, you'd need to clear the existing table rows.
By the way, this is very inefficient. You're reloading the entire table every 15 seconds. Multiple that by a few clients and you're practically performing a DoS attack on yourself. Consider using SignalR to push new changes to the clients as rows are added to the underlying data.
I have a simple ASP.NET page with a button and a textbox, I want to click the button and have "Hello" appear in the textbox.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="SOM.aspx.cs" Inherits="SOM" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div><br />
</div>
<asp:Button ID="MyBtn" runat="server" Text="Click" OnClick="SearchBtn_Click" />
<br />
<br />
<asp:TextBox ID="TextBox1" runat="server" Width="268px"></asp:TextBox>
in the code behind I am able to use Intellisence to autocomplete TextBox1.Text = "Hello";
but then when I try to debug, the project fails to build saying
The name TextBox1 does not exist in the current context
Is there a property that I need to set?
///Code behind
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Windows.Input;
public partial class SOM: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void SearchBtn_Click(object sender, EventArgs e)
{
//TextBox1.Text = "HI";
}
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
}
}
If any of the great answers here do not work, here's another solution that once caused me a few gray hairs, especially if you're using VS 2012.
If your project is a web application, delete the designer.cs file. Then right click on the aspx file and select "Convert to Web Application".
For as great as Visual Studio is, sometimes these stupid WTF things drive me absolutely nuts.
Your aspx page is not referencing the correct code behind.
In the head of your aspx page replace with
<%# Page Language="C#" AutoEventWireup="true" CodeFile="myName.aspx.cs" Inherits="myName" %>
That should work
NOTE: I now know this isn't the problem, I but updated my answer in case it solves someone else's problem.
If you are using a namespace somewhere between your codebehind or the aspx page, you have to make it consistent.
I will use "MyProject" as a sample namespace.
namespace MyProject
{
public partial class SOM: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void SearchBtn_Click(object sender, EventArgs e)
{
TextBox1.Text = "HI";
}
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
In your aspx page, change Inherits="SOM" to Inherits="MyProject.SOM".
Basically, in a nutshell, the problem is that dynamically generated triggers for an UpdatePanel can no longer be found (by ASP.NET) as soon as I add them as children of a custom control.
Since the amount of code I'm working on is quite substantial I've recreated the problem on a smaller scale, which will make it easier to debug.
The error thrown in my face is:
A control with ID 'theTrigger' could not be found for the trigger in UpdatePanel 'updatePanel'.
I'm not sure whether this implementation of a "custom control" is the right way to go about it, but I did not write the original implementation: I'm working with code written by a previous developer to which I cannot make large modifications. It looks a little unusual to me, but, alas, this is what I've been given.
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestWeb.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">
<div>
<asp:Panel runat="server" ID="panel">
</asp:Panel>
<asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="updatePanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="lblSomething" runat="server"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TestWeb
{
public partial class Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
UselessTableWrapper table = new UselessTableWrapper();
TableRow tr = new TableRow();
TableCell td = new TableCell();
LinkButton button1 = new LinkButton { ID = "theTrigger", Text = "Click Me" };
button1.Click += button1_Click;
td.Controls.Add(button1);
tr.Controls.Add(td);
table.AddRow(tr);
panel.Controls.Add(table);
// ### uncomment these lines (and comment the one above) to see it working
// ### without the custom control
/*
Table realTable = new Table();
realTable.Controls.Add(tr);
panel.Controls.Add(realTable);
*/
updatePanel.Triggers.Add(new AsyncPostBackTrigger { ControlID = "theTrigger", EventName = "Click" });
scriptManager.RegisterAsyncPostBackControl(button1);
}
protected void button1_Click(object sender, EventArgs e)
{
lblSomething.Text = "Random number: " + new Random().Next(100);
updatePanel.Update();
}
}
}
MyControl.cs
using System;
using System.Web.UI.WebControls;
namespace TestWeb
{
public class UselessTableWrapper : WebControl
{
private Table table = new Table();
protected override void OnPreRender(EventArgs e)
{
Controls.Add(table);
}
public void AddRow(TableRow row)
{
table.Controls.Add(row);
}
}
}
Any ideas would be greatly appreciated.
Edit
I've tried switching the OnPreRender event for this (found in a tutorial):
protected override void RenderContents(HtmlTextWriter writer)
{
writer.BeginRender();
table.RenderControl(writer);
writer.EndRender();
base.RenderContents(writer);
}
... hoping that it would fix it, but it does not.
this is the approach that I've taken with loading a ascx web control inside an aspx control from the code behind.
In the control:
namespace dk_admin_site.Calculations
{
public partial class AssignedFieldCalculation : System.Web.UI.UserControl
{
public static AssignedFieldCalculation LoadControl(Calculation initialData)
{
var myControl = (AssignedFieldCalculation) ((Page) HttpContext.Current.Handler).LoadControl(#"~\\Calculations\AssignedFieldCalculation.ascx");
myControl._initialData = initialData;
return myControl;
}
private Calculation _initialData;
public Calculation Data { get { return _initialData; } }
protected void Page_Load(object sender, EventArgs e) {}
}
}
in the web form code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
{
if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnRemoveCalculationFromField"))
{
//do something on the postback
}
else if (ScriptManager1.AsyncPostBackSourceElementID.StartsWith("ctl00$MainContent$calc") && (ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationUp") || ScriptManager1.AsyncPostBackSourceElementID.EndsWith("$btnMoveCalculationDown")))
{
//do something on the postback
}
}
foreach (Calculation calc in calculationCollection)
{
AssignedFieldCalculation asCalc = AssignedFieldCalculation.LoadControl(calc);
asCalc.ID = "calc" + calc.UniqueXKey;
pnlFieldCalculations.Controls.Add(asCalc);
foreach (Control ct in asCalc.Controls)
{
if (ct.ID == "btnMoveCalculationDown" || ct.ID == "btnMoveCalculationUp" || ct.ID == "btnRemoveCalculationFromField")
{
ScriptManager1.RegisterAsyncPostBackControl(ct);
}
}
}
}
A few things to note:
You need to make each control ID unique when adding it to the asp:Panel (called pnlFieldCalculations).
The LoadControl method allows you to pass initial arguments
ASP.Net Dropdownlist , on changing the value of drop down list and clicking the button it is not sending an upadted value to the New.aspx
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="ddl_test" runat="server" OnSelectedIndexChanged="ddl_test_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem>First Item</asp:ListItem>
<asp:ListItem>Second Item</asp:ListItem>
<asp:ListItem>Third Item</asp:ListItem>
</asp:DropDownList>
<asp:HiddenField ID="hdf_ddl" runat="server" />
<asp:Button ID="btn_test" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Test_DropDown : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
string passValue = ddl_test.SelectedValue.ToString();
string val = hdf_ddl.Value.ToString();
btn_test.Attributes.Add("onclick", "window.open('New.aspx?ddlValue=" + val + "', 'OpenPopWindow','left=250,top=100,width=500,height=500,toolbar=1,resizable=0,status=0,menubar=0,scrollbars=1');return false;");
//btn_test.OnClientClick = "window.open('New.aspx?ddlValue=" + val + "', 'OpenPopWindow','left=250,top=100,width=500,height=500,toolbar=1,resizable=0,status=0,menubar=0,scrollbars=1');return false;";
}
protected void ddl_test_SelectedIndexChanged(object sender, EventArgs e)
{
hdf_ddl.Value = ddl_test.SelectedValue.ToString();
}
}
Firstly, the assignment of OnClientClick is commented out.
Secondly, if you want the button to display the value after it has been selected, register OnClientClick in the ddl_test_SelectedIndexChanged event.
Move the following code:
btn_test.Attributes.Add("onclick", "window.open('New.aspx?ddlValue=" + val + "', 'OpenPopWindow','left=250,top=100,width=500,height=500,toolbar=1,resizable=0,status=0,menubar=0,scrollbars=1');return false;");
to your Page_Load event
You could send the windowopen function to the page via the registerstartupscript method.
If you want to have new window opened after the first button click you should register onclick event handler not in the Button1_Click method becase Button1_Click is executed only after click on the button. You can modify your page load method:
protected void Page_Load(object sender, EventArgs e)
{
string val = hdf_ddl.Value.ToString();
btn_test.Attributes.Add("onclick", "window.open('New.aspx?ddlValue=" + val + "', OpenPopWindow','left=250,top=100,width=500,height=500,toolbar=1,resizable=0,status=0,menubar=0,scrollbars=1');return false;");
}
But better way to do what you want is to avoid postbacks on dropdown selection and implement new window opening on client side.
What you are trying to do is to open a popup windows after the postback has happened. This can be performed with the use of injecting the script into the page. Basically you use the ClientScriptManager.RegisterClientScriptBlock and inject the popup window script using that method. Also, make sure that the last parameter which I think is to include the script tags is true which will execute the script as soon as the JavaScript code is injected into the page.
UPDATE:
Here is the implementation:
protected void Btn1_Click(object sender, EventArgs e)
{
string script =
"window.open('New.aspx','OpenPopWindow','width=500,height=500');";
ClientScriptManager clientScriptManager = Page.ClientScript;
if(!clientScriptManager.IsClientScriptBlockRegistered("OpenWindow"))
{
clientScriptManager.RegisterClientScriptBlock(typeof(_Default), "OpenWindow", script, true);
}
}