Within a site using a MasterPage, I have a page which has an UpdatePanel. Inside that, there is a ListBox which contains a list of users. There is also a dynamically generated list of checkboxes, which should have different values checked based upon which user is selected.
It works great the first time you select a user. However, when you select a second user, the original values remain - you see the checkboxes of both users checked.
.aspx
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<h1>Access Database Security Controls</h1>
<asp:UpdatePanel ID="SecurityControls" runat="server">
<ContentTemplate>
<asp:ListBox ID="AccessUsers" runat="server" Rows="15" SelectionMode="Single" OnSelectedIndexChanged="AccessUsers_SelectedIndexChanged" AutoPostBack="true"></asp:ListBox>
<asp:PlaceHolder ID="SecurityRoles" runat="server"></asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
code behind
protected void Page_Load(object sender, EventArgs e)
{
LoadAllRoles();
}
protected void LoadAllRoles()
{
for (int i = 0; i < 4; i++)
{
Label lbl = new Label();
lbl.ID = "lbl_" + i.ToString();
lbl.Text = i.ToString() + " lbl text here";
SecurityRoles.Controls.Add(lbl);
CheckBox cb = new CheckBox();
cb.ID = "cb_" + i.ToString();
SecurityRoles.Controls.Add(cb);
SecurityRoles.Controls.Add(new LiteralControl("<br />"));
}
}
protected void AccessUsers_SelectedIndexChanged(object sender, EventArgs e)
{
Control page = Page.Master.FindControl("MainContent");
Control up = page.FindControl("SecurityControls");
Control ph = up.FindControl("SecurityRoles");
CheckBox cbRole = (CheckBox)ph.FindControl("cb_" + AccessUsers.SelectedValue);
if (cbRole != null)
cbRole.Checked = true;
}
I've tried doing cb.Checked = false; when I am creating the checkboxs, but even on the partial postbacks, the SecurityRoles placeholder control starts out empty.
How do I get the checkboxes to clear?
You can try to uncheck all other check-boxes before you check one.
foreach (Control c in ph.Controls)
{
if(c is CheckBox)
{
((CheckBox)c).Checked=false;
}
}
Related
I have a ImageButton which will show Calendar after it is clicked. I want to stop page refresh when the ImageButton is clicked, but I've tried a couple of ways and none of them work. Is it possible to avoid page refresh and just show the calendar after the Image Button is clicked?
Here is my c# code
TableRow first = new TableRow();
TableCell four = new TableCell();
ImageButton btnDateToggle = new ImageButton();
btnDateToggle.ID = $"btnDateToggle_{j}";
btnDateToggle.ImageUrl = "images/icon2.gif";
btnDateToggle.Click += new ImageClickEventHandler(BtnDateToggle_Click);
Calendar dateddl = new Calendar();
dateddl.ID = $"dateddl_{j}"
dateddl.Width = 250;
dateddl.Visible = false;
dateddl.SelectionChanged += new EventHandler(Dateddl_SelectionChanged);
four.Controls.Add(btnDateToggle);
four.Controls.Add(dateddl);
first.Cells.Add(four);
tasksTable.Rows.Add(first);
ChildPane.ContentContainer.Controls.Add(tasksTable);
ChildAccordion.Panes.Add(ChildPane);
ParentPane.ContentContainer.Controls.Add(ChildAccordion);
MasterAccordion.Panes.Add(ParentPane);
MyContent.Controls.Add(MasterAccordion);
ChildPane and ParentPane are AccordionPane Object. ChildAccordion is an Accordion Object
protected void BtnDateToggle_Click(object sender, EventArgs e)
{
string btnDateToggleID = ((Control)sender).ID;
string index = btnDateToggleID.Substring(btnDateToggleID.IndexOf('_') + 1);
Calendar dateddl = (Calendar)FindControlRecursive(Page, $"dateddl_{index}");
dateddl.Visible = !dateddl.Visible;
}
protected void Dateddl_SelectionChanged(object sender, EventArgs e)
{
Calendar dateddl = (Calendar)sender;
string dateddlID = dateddl.ID;
string index = dateddlID.Substring(dateddlID.IndexOf('_') + 1);
TextBox textBox = (TextBox)FindControlRecursive(Page, $"txtDate_{index}");
dateddl.Visible = false;
textBox.Text = dateddl.SelectedDate.ToShortDateString();//.ToString("MM/dd/yyyy");
}
Here is my client side code (.aspx)
<asp:Content ID="Content1" runat="server">
<div>
<asp:Panel ID="MyContent" runat="server">
<ajaxToolkit:Accordion ID="MasterAccordion" runat="server"> </ajaxToolkit:Accordion>
</asp:Panel>
</div>
I've added two text boxes dynamically on the aspx page.
I would like to get values from those two text boxes on the server side after postback (after Btn1 is clicked).
And here is my first problem - controls are not found.
I've tried to find controls with:
Page.FindControl("txt4");
What is wrong with this? Isn't the whole page posted back with all the controls in it?
My other question is - where in the code to get those values? In the Page_load event, before they are re-added? I guess when Btn1_Click event is triggered, those two controls are already re-added, so values from original postback are lost? (Page_load event is triggered before Btn1_Click).
I am really struggling with this.
It is much easier if controls are added through markup - they are directly accesible in code behind by theirs ID. But on the project that I work currently controls are mostly added dynamically, and a lot of them.
Code behind:
public partial class About : Page
{
protected void Page_Load(object sender, EventArgs e)
{
btn1.Click += Btn1_Click;
if(IsPostBack)
{
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if(txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
}
private void Btn1_Click(object sender, EventArgs e)
{
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
Markup:
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Button ID="btn1" runat="server" Text="Button" />
<asp:Panel ID="panel1" runat="server" ClientIDMode="Static">
</asp:Panel>
</asp:Content>
UPDATE:
I've updated my code with:
protected void Page_Init(object sender, EventArgs e)
{
if(IsPostBack)
{
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
string st1 = txt4.Text;
string st2 = txt5.Text;
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
I've checked the code in debugger - controls are added on postback, but values for st1, st2, txt4_dynamic and txt5_dynamic are still empty / null.
UPDATE 2:
There were two problems:
Finding control should be done with:
Page.Controls[0].FindControl("MainContent").FindControl("txt4");
Code above finds controls text only in controls events (and they are triggered after Page_Load).
So: Everything can stay as I originally posted - the only change needed is code for finding control, which must be in click event. If this same code is in Page_Load event, it will not work.
Please change the code to as below (basically move the dynamic control creation/addition to Page_Init):
public partial class About : Page
{
protected void Page_Init(object sender, EventArgs e)
{
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
}
protected void Page_Load(object sender, EventArgs e)
{
btn1.Click += Btn1_Click;
if (IsPostBack)
{
System.Web.UI.Control txt4_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
private void Btn1_Click(object sender, EventArgs e)
{
System.Web.UI.Control txt4_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
Control tree is created at server side on each postback. Since controls are added dynamically they need to be added on each postback, which you are already doing.
Reason for moving that code to Page_Init event is that, values posted from clientside are set in LoadPostData event which happens after Page_Init and before Page_Load.
When you have the code in Page_Init, by the time LoadPostData event happens control tree is already created and posted value is correctly set.
When you had the code in Page_Load, LoadPostData event happened even before the control was created and posted value was not set.
I am quite new to ASP and I have been stuck on an issue for about a week. The issue is probably something to do with the Asp Page Life Cycle but I am unable to find how this can be resolved. The issue is that skipto(..) is never called when I click the LinkButton (that were created on first Page Load), which means the LinkButtons are not rendered.
Sample Code below:
// Code Behind
protected void Page_Load(object sender, EventArgs e)
{
loadData();
if (!Page.IsPostBack)
{
skiptof();
}
}
public void loadData() {
// Loads from database
}
public void skipto(object sender, EventArgs e)
{
LinkButton btn = sender as LinkButton;
if (btn != null)
{
if (btn.CommandArgument != null && btn.CommandArgument != "0")
{
int currPage = 1;
int.TryParse(btn.CommandArgument, out currPage);
skiptof(currPage);
}
}
}
public void skiptof(int currPage = 1)
{
int lastPage = // calculate from LoadData()
string pageDisabled = "";
// pages
HtmlGenericControl ul = new HtmlGenericControl("ul");
while (pageCount <= lastPage)
{
// Disable the current page
pageDisabled = pageCount == currPage ? " class=\"disabled\"" : "";
HtmlGenericControl pagesli = new HtmlGenericControl("li");
if (pageDisabled != "")
{
pagesli.Attributes.Add("class", "disabled");
}
LinkButton pagesPageLink = new LinkButton();
pagesPageLink.Click += new EventHandler(skipto);
pagesPageLink.CommandArgument = pageCount.ToString();
pagesPageLink.Text = pageCount.ToString();
pagesli.Controls.Add(pagesPageLink);
ul.Controls.Add(pagesli);
pageCount += 1;
}
pagination.Controls.Add(ul);
}
// page
<asp:ScriptManager ID="ScriptManager1" runat="server"/>
<asp:UpdatePanel runat="server" id="UpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<div id="details" runat="server"></div>
<div class="pagination text-center" id="pagination" runat="server"></div>
</ContentTemplate>
</asp:UpdatePanel>
Your problem is:
You didn't bind the data again on postback, I've modified your code a little bit, there are several problems:
in the method skipof:
public void skiptof(int currPage = 1) {
//Clear the controls here then add them again
pagination.Controls.Clear();
int lastPage = // calculate from LoadData()
string pageDisabled = "";
HtmlGenericControl ul = new HtmlGenericControl("ul");
while (pageCount <= lastPage) {
// Disable the current page
pageDisabled = pageCount == currPage ? " class=\"disabled\"" : "";
HtmlGenericControl pagesli = new HtmlGenericControl("li");
if (pageDisabled != "") {
pagesli.Attributes.Add("class", "disabled");
}
LinkButton pagesPageLink = new LinkButton();
// you can directly assign the method to be called here, there is no need to create a new EventHandler
pagesPageLink.Click += PagesPageLink_Click;
pagesPageLink.CommandArgument = pageCount.ToString();
pagesPageLink.Text = pageCount.ToString();
pagesli.Controls.Add(pagesPageLink);
ul.Controls.Add(pagesli);
pageCount += 1;
}
pagination.Controls.Add(ul);
}
You didn't bind the data again in postback, so I modified it:
Page Load:
protected void Page_Load(object sender, EventArgs e) {
//Remove the Page.IsPostBack checking
skiptof();
}
Please take note that the controls you added dynamically will be cleared and you have to add it again on postback to avoid data lost.
Then you'll be able to get the value on PagesPageLink_Click event:
The whole sample is here:
http://pastie.org/10503291
I'm adding TextBoxes dynamically and when I click a submit button and have a postback, I can't see the values entered into the TextBoxes, all are coming up emtpy. Here's the .aspx page...\
form id="form1" runat="server">
<asp:PlaceHolder ID="phFormContent" runat="server">
</asp:PlaceHolder>
<br /><br />
<asp:Button ID="btnAddForm" runat="server" Text="Add Form" OnClick="btnAddForm_Click" />
<asp:Button ID="btnSubmitForms" runat="server" Text="Submit Forms" OnClick="btnSubmit_Click" />
</form>
...here's how I add the TextBoxes to the form on clicking btnAddForm...
protected void btnAddForm_Click(object sender, EventArgs e)
{
// Create Labels
Label lblName = new Label();
lblName.Text = "NAME:";
Label lblNumber = new Label();
lblNumber.Text = "NUMBER:";
Label lblAddress = new Label();
lblAddress.Text = "ADDRESS:";
Label lblCompany = new Label();
lblCompany.Text = "COMPANY:";
// Create Text Boxes
TextBox txtName = new TextBox();
TextBox txtNumber = new TextBox();
TextBox txtAddress = new TextBox();
TextBox txtCompany = new TextBox();
// Create submit button
Button btnSubmit = new Button();
btnSubmit.Text = "SUBMIT";
// Create panel and add controls
Panel pnlForm = new Panel();
pnlForm.Controls.Add(lblName);
pnlForm.Controls.Add(txtName);
pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
pnlForm.Controls.Add(lblNumber);
pnlForm.Controls.Add(txtNumber);
pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
pnlForm.Controls.Add(lblAddress);
pnlForm.Controls.Add(txtAddress);
pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
pnlForm.Controls.Add(lblCompany);
pnlForm.Controls.Add(txtCompany);
pnlForm.Controls.Add(new LiteralControl("<hr />"));
pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
panels.Add(pnlForm);
foreach (Control panel in panels)
{
phFormContent.Controls.Add(panel);
}
}
...and here's how I try to extract the fields for each individual panel added...
private static void GetFormFields(Control panelControl)
{
ControlCollection controls = panelControl.Controls;
foreach (Control childControl in panelControl.Controls)
{
if (childControl.GetType().ToString() == "System.Web.UI.WebControls.TextBox")
{
TextBox txt = childControl as TextBox;
fields.Add(txt);
}
else
{
GetFormFields(childControl);
}
}
}
panels and fields are static List, each panel containing four fields. I pass GetFormFields an individual panel reference...
private static List<Control> panels = new List<Control>();
private static List<TextBox> fields = new List<TextBox>();
Try dynamically adding them on the Page_Init event. Typically this will ensure they persist through PostBack. If you can't do this, you'll have to look at preserving their data manually by storing in ViewState.
Looks like the text boxes are not being included in the VIEWSTATE for the page, so are lost on postback.
There's some detail about what happens in this scenario here :
http://msdn.microsoft.com/en-us/library/kyt0fzt1(v=VS.71).aspx
I'm having problems with finding my controls in my dynamically created literal control. I want to be able to grab the value in the label with the fnameID(x) id.
ASPX:
<div>
<asp:Panel ID="Panel1" runat="server">
</asp:Panel>
</div>
<asp:Button ID="Button1" runat="server" Text="Button"
onclick="Button1_Click" />
CODE BEHIND:
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 50; i++)
{
CheckBox _checkbox = new CheckBox();
_checkbox.ID = "dynamicCheckListBox" + Convert.ToString(i);
Panel1.Controls.Add(_checkbox);
Panel1.Controls.Add(new LiteralControl("<Label id='fnameID"
+ i + "' >test" + i + "</Label><br/>"));
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Label lbl = (Label)Panel1.FindControl("fnameID0");
Response.Write(lbl.Text);
}
Currently I am getting the following error when I click on the button:
Object reference not set to an instance of an object.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
{
Label lbl = (Label)Page.FindControl("fnameID0");
**Response.Write(lbl.Text);**
}
Try explicitly setting the ID of the control you generate:
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 50; i++)
{
CheckBox _checkbox = new CheckBox();
_checkbox.ID = "dynamicCheckListBox" + Convert.ToString(i);
Panel1.Controls.Add(_checkbox);
LiteralControl dynLabel = new LiteralControl("<Label id='fnameID"
+ i + "' >test" + i + "</Label><br/>");
dynLabel.ID = "fnameID" + i.ToString();
Panel1.Controls.Add(dynLabel);
}
}
You're getting the null reference exception because no control with the specified ID is being found, so FindControl is returning null, and you can't get the Text property of a null.