I want to load an aspx page having a textbox and a button beside it and with any numeric value in the textbox. On clicking the button beside the textbox I want to generate another set of textbox containing a non-repeating random number and a button beside it and this should continue again if we click the last generated button.
In my code I am getting the output but, in my output the page gets loaded and for the first time it displays a textbox containing '0' and a button but when I click on the generate button it is generating the textboxes and buttons but they are getting placed above the very first textbox containing '0' and rest of all the newly generated textboxes containing with random numbers along with buttons are placed over the first textbox. I want the first textbox to be on the top and rest of them gets generated below it.
I am new to C#, asp.net. Please Help!!!
Following is my code:
<!DOCTYPE html>
<script runat="server">
static int limit = 0;
static int[] x = new int[100];
protected void Page_Load(object sender, EventArgs e)
{
if(Page.IsPostBack)
x[limit] = new Random().Next(100);
}
protected void bGenerate_Click(object sender, EventArgs e)
{
limit++;
}
protected void tbNum_TextChanged(object sender, EventArgs e)
{
//tbNum.Text ="";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Creates Controls Dynamically</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table style="width:100%;">
<%
for (int counter = 0; counter <= limit; counter++)
{
%>
<tr>
<td>
<input type="text" name="tbNum" id="tbNum" value="<%=x[counter]%>"/>
<%--<asp:TextBox ID="tbNum" runat="server" Width="382px" OnTextChanged="tbNum_TextChanged"></asp:TextBox>--%>
</td>
<td>
<asp:Button ID="bGenerate" runat="server" Text="GENERATE" Width="290px" OnClick="bGenerate_Click" />
</td>
</tr>
<%
}
%>
</table>
</div>
</form>
</body>
You should move the code that generates new random values to the bGenerate_Click event:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
x[0] = new Random().Next(100);
}
protected void bGenerate_Click(object sender, EventArgs e)
{
limit++;
x[limit] = new Random().Next(100);
}
The problem with your existing code is that when you click on the Generate button, the code in Page_Load is executed before bGenerate_Click.
Related
I have a page with a number of controls of type MyControl added dynamically. The count is stored in the ViewState, and only incremented with a button click.
In MyControl, I have a TextBox control, and a Label control. When the text is changed in the textbox, the value is multiplied by 2 and displayed in the label control.
To do this, I have added an OnTextChanged event and set AutoPostBack to true.
My problem is this: when I have any number of MyControl's on the page, and change the text in any of the textboxes, the label is updated and the values are retained on postback.
However, if I click the increment button on the page, all the values in the textboxes and labels are lost.
My code:
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Test.Default" EnableViewState="true" %>
<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
Count:
<asp:Label ID="lblCount" runat="server"></asp:Label>
<asp:Button ID="btnAdd" runat="server" OnClick="btnAdd_Click" Text="+" />
<asp:Panel ID="pnlControls" runat="server"></asp:Panel>
</form>
</body>
</html>
Default.aspx.cs
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
int count = 0;
//if not postback, then set count and store in viewstate
if (!Page.IsPostBack)
{
count = 1;
ViewState["count"] = count;
}
LoadControls();
}
protected void btnAdd_Click(object sender, EventArgs e)
{
//increment count
ViewState["count"] = (int)ViewState["count"] + 1;
pnlControls.Controls.Clear();
LoadControls();
}
private void LoadControls()
{
//add controls to page
for (int i = 0; i < (int)ViewState["count"]; i++)
{
MyControl con = (MyControl)LoadControl("MyControl.ascx");
con.ID = i.ToString();
pnlControls.Controls.Add(con);
}
//set count label
lblCount.Text = ViewState["count"].ToString();
}
}
MyControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="Test.MyControl" EnableViewState="true" %>
<div>
<asp:TextBox ID="txtField" runat="server" OnTextChanged="txtField_TextChanged" AutoPostBack="true"></asp:TextBox>
<asp:Label ID="lblAnswer" runat="server" Text="answer:"></asp:Label>
</div>
MyControl.ascx.cs
public partial class MyControl : System.Web.UI.UserControl
{
public string Text;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void txtField_TextChanged(object sender, EventArgs e)
{
lblAnswer.Text = (int.Parse(txtField.Text) * 2).ToString();
}
}
Am I missing something obvious? How can I keep the values when the button is clicked?
The reason you lose the info of MyControl(s..) is when you click the button you clear them:
pnlControls.Controls.Clear();
If you want to keep the values I recomended you to use Session variables, for example an array when you fire "txtField_TextChanged" to save "lblAnswer.Text", be carefull with the ID's to differentiate from each other in the Session variable.
Finally, I'd put "LoadControls();" inside Page_Load, outside I think It's redundant.
I am trying to generate a dynamic radio button list, but the issue is that the dynamic list does not show on page load. Only the Submit button shows. Here is the code I am using:
<asp:PlaceHolder runat="server" ID="PlaceHolder1"/>
<asp:Button runat="server" ID="Button1" OnClick="Button1_Click" Text="Submit" />
<asp:Label runat="server" ID="Label1"/>
protected void Page_Load(object sender, EventArgs e)
{
LoadControls();
}
protected void Button1_Click(object sender, EventArgs e)
{
var radioButtonList = PlaceHolder1.FindControl("1") as RadioButtonList;
Label1.Text = radioButtonList.SelectedValue;
}
private void LoadControls()
{
var tmpRBL = new RadioButtonList();
tmpRBL.ID = "1";
for (int i = 1; i <= 5; i++)
{
var tmpItem = new ListItem(i.ToString(), i.ToString());
tmpRBL.Items.Add(tmpItem);
}
PlaceHolder1.Controls.Add(tmpRBL);
}
WebForm1.aspx
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder runat="server" ID="PlaceHolder1"/>
<asp:Button runat="server" ID="Button1" OnClick="Button1_Click" Text="Submit" />
<asp:Label runat="server" ID="Label1"/>
</div>
</form>
</body>
</html>
WebForm1.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
LoadControls();
}
protected void Button1_Click(object sender, EventArgs e)
{
var radioButtonList = PlaceHolder1.FindControl("1") as RadioButtonList;
Label1.Text = radioButtonList.SelectedValue;
}
private void LoadControls()
{
var tmpRBL = new RadioButtonList();
tmpRBL.ID = "1";
for (int i = 1; i <= 5; i++)
{
var tmpItem = new ListItem(i.ToString(), i.ToString());
tmpRBL.Items.Add(tmpItem);
}
PlaceHolder1.Controls.Add(tmpRBL);
}
}
}
It works correct. I hope it will be helpful.
You could define an empty RadioButtonList control which you then populate with items on Page_Load. Would have the advantage that you don't have to create it manually. Also using the DataBind mechanism the control offers you together with an ObjectDataSource is a better solution (the Select method of the ObjectDataSource should return the items).
But aside this, maybe AutoEventWireup of the #Page directive (first line in the markup of the ASPX page) is set to false. If so the Page_Load event handler is not called. The directive usually looks like this:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
I copied the rest of your code and everything runs just fine.
I have been searching around and I am lost on how to do what I am attempting to do.
I am trying to create a form where the first column is a list of names, and the next column is all dropdown lists. The idea is that for each name the user will pic a value. Each name may require two, or three or more values. I want to create a dynamic form where a user can click add in the row and another dropdown list appears.
Ex.
"Name" | Add Button | DropDown
then when I click add...
"Name" | Add Button | DropDown | DropDown
and have it keep going.
I am able to create the form and I have it working creating the dropdown lists. The problem is that I am adding the controls on the ItemCommand of a repeater, so they must be recreated every time. Because of this I cannot find a way to keep the values selected in each dropdown, when I have to recreate them.
Typically no more than two dropdowns are required but there are a few cases where three is needed, and it could arise for more. I would like to keep this dynamic as possible.
I know that if I added the dropdown's in the page Init they would be persisted on the postback, but at least in my design the user has to click add to get another drop down.
Is there a way to capture the data from these dropdowns then reload them every time? Or a better way to achieve this functionality?
Thank You for your help.
Here is some of the asp and code behind that I am using. This is functioning as I wish, but I don't know how to keep the data on a postback, as all of the dropdown lists I add are lost.
ASP:
<table>
<asp:Repeater ID="repChemicals" runat="server" OnItemCommand="repChemicals_OnItemCommand">
<ItemTemplate>
<tr>
<td>
<asp:HiddenField ID="hfNumber" runat="server" />
<%# Eval("ChemicalName") %>
</td>
<td>
<asp:Button runat="server" ID="btnAdd" Text="Add" CommandArgument="ADD" />
</td>
<td>
<div id="divContainer" runat="server">
<asp:DropDownList runat="server" Width="60px" ID="ddlTest"></asp:DropDownList>
</div>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<Chem> Chemicals = new List<Chem>();
Random rnd = new Random();
for (int z = 0; z <= 10; z++)
{
List<string> t = new List<string>();
Chem a = new Chem()
{
ChemicalName = "Chemical" + z.ToString()
};
Chemicals.Add(a);
}
repChemicals.DataSource = Chemicals;
repChemicals.DataBind();
}
}
public void repChemicals_OnItemCommand(object sender, RepeaterCommandEventArgs e)
{
int number = 0;
foreach (RepeaterItem i in repChemicals.Items)
{
HiddenField hf = (HiddenField)repChemicals.Items[i.ItemIndex].FindControl("hfNumber");
if (i.ItemIndex == e.Item.ItemIndex)
{
if (!string.IsNullOrWhiteSpace(hf.Value))
{
number = Convert.ToInt16(hf.Value) + 1;
}
else
{
number = 1;
}
hf.Value = number.ToString();
}
else
{
if (!string.IsNullOrWhiteSpace(hf.Value))
{
number = Convert.ToInt16(hf.Value);
}
else
{
number = 0;
}
}
for (int x = 0; x < number; x++)
{
DropDownList ddl = new DropDownList();
ddl.Style.Add("width", "60px");
ddl.ID = "ddl" + i.ToString() + x.ToString();
ddl.Style.Add("Margin-right", "3px");
ddl.Attributes.Add("runat", "server");
ddl.DataSource = DataSource();
ddl.DataBind();
Control c = repChemicals.Items[i.ItemIndex].FindControl("divContainer");
c.Controls.Add(ddl);
}
}
Some of the loops are for creating test data. Basically I am storing a number of dynamic controls on each row in a hiddenfield. Then on the item command I loop through all of the rows and recreate all of the previously existing ddl's, and add one to the row that teh command came from.
This isn't exactly answering your question, but it accomplishes your ultimate goal in a less complex way and one that takes advantage of built in ASP.NET controls so maintaining state between postbacks is taken care of for you.
It utilizes jQuery, jQuery UI and a DropDownChecklist plugin.
ASPX
<!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>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/ui.dropdownchecklist.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/themes/base/jquery-ui.css"/>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<asp:Repeater ID="repChemicals" runat="server">
<ItemTemplate>
<tr>
<td>
<%# Container.DataItem %>
</td>
<td>
<div id="divContainer" runat="server">
<asp:ListBox ID="lstAttributes" SelectionMode="Multiple" runat="server"></asp:ListBox>
</div>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<asp:Button ID="btnPostback" Text="Postback" runat="server"/>
</div>
</form>
</body>
</html>
C#
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace PersonAttributes
{
public partial class People : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
repChemicals.ItemCreated += RepChemicalsOnItemCreated;
var chemicals = new[] {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron"};
if(!IsPostBack)
{
repChemicals.DataSource = chemicals;
repChemicals.DataBind();
}
var dropDownChecklist = "$(document).ready(function () { $('select').dropdownchecklist(); });";
ScriptManager.RegisterStartupScript(this,GetType(),"initDropDownChecklist",dropDownChecklist,true);
}
private void RepChemicalsOnItemCreated(object sender, RepeaterItemEventArgs repeaterItemEventArgs)
{
var lst = repeaterItemEventArgs.Item.FindControl("lstAttributes") as ListBox;
if (lst == null)
return;
lst.DataSource = new[] {"Option 1", "Option 2", "Option 3"};
}
}
}
See it in action at CodeRun.
I have a grid view in my main page and I display some data for user(using BindGrid method).this grid view has some command buttons for each row that perform some operation like Update. when user clicks on update button I show to him/her a user control to update values.and when user clicks on update I want grid bind to new data(I want call BindGrid for new data). How I can do this and call a method in main page from user control?
Edit 1)
I wrote this code for user control:
public partial class SomeUserControl : System.Web.UI.UserControl
{
public event EventHandler StatusUpdated;
private void FunctionThatRaisesEvent()
{
if (this.StatusUpdated != null)
this.StatusUpdated(new object(), new EventArgs());
}
public void Page_Load(object sender, EventArgs e)
{
//....
}
protected void Button1_Click(object sender, EventArgs e)
{
FunctionThatRaisesEvent();
}
}
and the designer for user control :
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SomeUserControl.ascx.cs" Inherits="SomeUserControl" %>
<asp:Button ID="Button1" runat="server" Text="Update" Height="70px"
onclick="Button1_Click" Width="183px" />
and add this code for main page:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Unnamed1_Click(object sender, EventArgs e)
{
SomeUserControl userControl = (SomeUserControl)LoadControl("SomeUserControl.ascx");
userControl.StatusUpdated += new EventHandler(userControl_StatusUpdated);
Panel1.Controls.Add(userControl);
}
void userControl_StatusUpdated(object sender, EventArgs e)
{
GetDate();
}
private void GetDate()
{
TextBox1.Text = DateTime.Today.ToString();
}
and designer for main page:
<%# Register src="SomeUserControl.ascx" tagname="SomeUserControl" tagprefix="uc1" %>
<!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:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<asp:UpdatePanel ID="upd1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button runat="server" Text="Add User Control" Height="44px" ID="Nims"
onclick="Unnamed1_Click" Width="133px" />
<asp:Panel ID="Panel1" runat="server" BackColor="#FFFFCC"></asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
but it does not work and nothing happend. even I add break point for click user control button code but it seems that event not raise.
Raise the event from the user control, and handle the event from the main page. Check out this question.
//** EDIT **//
You are adding the user control dynamically on button click. When you click the button on your user control it first will initiate postback on the main page - now your user control no longer exists (which is why the event is not raised). If you change your main page designer to look like this:
<%# Register Src="SomeUserControl.ascx" tagname="SomeUserControl" tagprefix="uc1" %>
<!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 id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<asp:UpdatePanel ID="upd1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button runat="server" Text="Add User Control" Height="44px" ID="Nims"
onclick="Unnamed1_Click" Width="133px" />
<asp:Panel ID="Panel1" runat="server" BackColor="#FFFFCC">
<uc1:SomeUserControl ID="userControl" runat="server" />
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
and your code-behind to look like this
protected void Page_Load(object sender, EventArgs e)
{
userControl.StatusUpdated += new EventHandler(userControl_StatusUpdated);
}
void userControl_StatusUpdated(object sender, EventArgs e)
{
GetDate();
}
private void GetDate()
{
TextBox1.Text = DateTime.Today.ToString();
}
you will see what I mean. Try setting breakpoints on the page load events of your main page and your user control to see exactly the order in which things happen.
You can register an event in your user control, raise the event when user clicks on update button and capture that event on the page.
http://codebetter.com/brendantompkins/2004/10/06/easily-raise-events-from-asp-net-ascx-user-controls/
you need to use event handler for that
define event handler in your ascx page
public event EventHandler ButtonClickDemo;
when you are performing update or delete event use following code there for event handler.
ButtonClickDemo(sender, e);
in parent page use following
protected void Page_Load(object sender, EventArgs e)
{
btnDemno.ButtonClickDemo += new EventHandler(btn_Click);
}
the function to bind grid of parent page
protected void btn_Click(object sender, EventArgs e)
{
BindGrid();
}
above code will call BindGrid function of parent page.
I have the following webform:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="TestWebApp.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:TextBox ID="txtMultiLine" runat="server"
Width="400px" Height="300px" TextMode="MultiLine"></asp:TextBox>
<br />
<asp:Button ID="btnSubmit" runat="server"
Text="Do A Postback" OnClick="btnSubmitClick" />
</div>
</form>
</body>
</html>
and each time I post-back the leading line feeds in the textbox are being removed. Is there any way that I can prevent this behavior?
I was thinking of creating a custom-control that inherited from the textbox but I wanted to get a sanity check here first.
I ended up doing the following in the btnSubmitClick()
public void btnSubmitClick(object sender, EventArgs e)
{
if (this.txtMultiLine.Text.StartsWith("\r\n"))
{
this.txtMultiLine.Text = "\r\n" + this.txtMultiLine.Text;
}
}
I must be really tired or sick or something.
I think that the problem here is in the way that the browser renders the textarea contents, not with ASP.NET per se. Doing this:
public void btnSubmitClick(object sender, EventArgs e) {
this.txtMultiLine.Text = "\r\n" + this.txtMultiLine.Text;
}
will let you reach the desired screen output, but you'll add an extra newline to the Text that the user didn't enter.
The ideal solution would be for the TextBox control in ASP.NET to always write the newline AFTER writing the open tag and BEFORE writing the contents of Text. This way, you'd reach the desired effect without trumping the contents of the textbox.
We could inherit from TextBox and fix this by overriding RenderBeginTag:
public override void RenderBeginTag(HtmlTextWriter writer) {
base.RenderBeginTag(writer);
if (this.TextMode == TextBoxMode.MultiLine) {
writer.Write("\r\n"); // or Environment.NewLine
}
}
Now, creating a new class for this small issue seems really overkill, so your pragmatic approach is completely acceptable. But, I'd change it to run in the PreRender event of the page, which is very late in the page lifecycle and would not interfere with the processing of the submitted text in the OnSubmit event of the button:
protected void Page_Load(object sender, EventArgs e) {
this.PreRender += Page_OnPreRender;
}
protected void Page_OnPreRender(object sender, EventArgs e) {
this.txtMultiLine.Text = "\r\n" + this.txtMultiLine.Text;
}