Update dynamic control inside a updatepanel with a dynamic created child - c#

I've been searching how to acomplish this but I have'nt been able to find a solution. I simplified the problem from my original project where I have to achieve this to the following:
In the .aspx I have:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="udpDynamicControls" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder" runat="server">
</asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
And in code behind:
public partial class _Default : System.Web.UI.Page
{
protected string TextToShow
{
get
{
return Session["TextToShow"] == null ? "Original Text" :
Session["TextToShow"].ToString();
}
set { Session["TextToShow"] = value; }
}
protected void Page_Init(object sender, EventArgs e)
{
var lblToChange = new Label
{
ID = "lblToChange",
Text = TextToShow
};
var chkChangeText = new CheckBox
{
ID = "btnChangeText",
Text = "Change Text",
AutoPostBack = true
};
chkChangeText.CheckedChanged += ChkChangeTextClick;
PlaceHolder.Controls.Add(lblToChange);
PlaceHolder.Controls.Add(chkChangeText);
}
private void ChkChangeTextClick(object sender, EventArgs e)
{
var check = (CheckBox) sender;
TextToShow = check.Checked ? "Text Changed" : "Original Text";
udpDynamicControls.Update();
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
As you can see what i'm trying to do si to update the label when the check box is changed threw the update panel. But the udpDynamicControls.Update(); Doesnt fire the page_init event, where it would take its new value. I already checked out similar questions but I believe this is a diferent scenario.
I will be very thankfull to anybody that could help. I apologize for any bad english.

So I resolved my problem on my original project some other way, but I thought I might as well post the answer to what I did in case somebody has the same problem, the they might use the same solution.
Since I was depending on the page_init to run again after the update just to update the new value for my control and this wasn't happing, then a possible solution would be to update the value of the control in the check box changed event, where as the label is already created, and in the next page life cycle run, it would persist its value.
So the only thing I changed was the ChkChangeTextClick Event and the end result was:
protected void ChkChangeTextClick(object sender, EventArgs e)
{
var check = (CheckBox) sender;
TextToShow = check.Checked ? "Text Changed" : "Original Text";
((Label) PlaceHolder.FindControl("lblToChange")).Text = TextToShow;
}
Replacing:
udpDynamicControls.Update();
For:
((Label) PlaceHolder.FindControl("lblToChange")).Text = TextToShow;
Come to think about it, its a more simple approach, in my original project I have several dynamic controls and I just set a pattern in my controls ID to find the ones I need and change the values. The events of the controls don't get lost and I can show the updated information without the browser postback.
I hope this is of any help to anyone in the future, because I almost ripped all my hair out with this.

Related

How do you get POSTed value from dynamically populated dropdownlist without the use of UpdatePanel?

I have a Web Form dependent on a Master Page, that contains a simple Form like this:
<asp:TextBox runat="server" ID="txtValue"></asp:TextBox>
<asp:DropDownList runat="server" ID="ddlProduct" />
<asp:Button runat="server" ID="btnConfirm" Text="Confirm" OnClick="btnConfirm_OnClick" />
on Page_Load I dynamically populate the DropDownList with values:
foreach(var product in products)
{
ListItem item = new ListItem(product.Nazev, product.ProductId.ToString());
ddlProduct.Items.Add(item);
}
Now .. normally if the DropDownList was populated statically, I would go with this, to get my selected value out of it:
protected void btnConfirm_OnClick(object sender, EventArgs e)
{
string selectedProduct = ddlProduct.SelectedValue;
}
But this is a no-go in this situation. Hence I try to directly get the selected value from POSTed parameters with one of those approaches (which are in fact practically the same):
protected void btnConfirm_OnClick(object sender, EventArgs e)
{
string selectedProduct = Request.Form.Get(ddlProdukt.ClientID);
string selectedProduct2 = Request.Params[ddlProdukt.ClientID];
}
But it doesn't work. If I debug it, the actual "id/name" of the DropDownList in the POSTed Form (Request.Params) is:
"ctl00$MainContent$ddlProdukt"
whereas the ClientId my approach gives me is:
"ctl00_MainContent_ddlProdukt"
I can't figure out, why does it replace '_' for '$' in the ID of my DDL control.. It seems to be such a trivial thing. There should be a better way to find out the right ID, than replacing the character, right?
Is there some other way I should "look/ask" for the selected value?
*Take into account, that I'am not looking for a solution with an UpdatePanel. I know, that using an UpdatePanel would result in the DDL value being sucessfully selected after the Postback, but that is NOT the answer I'm looking for here.
Thank you for any input.
If you still need to use the Request.Form.Get or Request.Params you should call it on ddlProdukt.UniqueID as it's separator is '$' versus '_' on the .ClientID
As requested an example. This code and the <asp:DropDownList ID="ddlProduct" runat="server"></asp:DropDownList> are on the aspx page, not the Master.
protected void Page_Load(object sender, EventArgs e)
{
//bind data not here
if (IsPostBack == false)
{
//but inside the ispostback check
ddlProduct.Items.Add(new ListItem("Item 1", "1"));
ddlProduct.Items.Add(new ListItem("Item 2", "2"));
ddlProduct.Items.Add(new ListItem("Item 3", "3"));
ddlProduct.DataBind();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = ddlProduct.SelectedValue;
}

Setting nested control values in a asp:formview from C# code behind

I was approaching this from the angle of controlling the asp:SqlDataSource bound to the controls inside the formview that is part of this topic and was getting no where rather fast, so I opt'd to close that thread and approach this at the control level inside the formview instead as it seemed to make a lot more sense to me.
So for back ground The code below is intended to inject string values listed in the first two lines of the screen clip below (and the two corresponding Response.Write's at the bottom of the included code block).
What I am trying to do, is use FindControl to set the Text value in the case of these items (but I have a few asp:checkbox's to deal with after getting this done as well that will need the same treatment.) and for now I'm just focusing on these two controls. The first is a asp:label
<asp:Label runat="server" ID="SubmitByLbl" Text='<%# Eval("SubmitBy") %>' ></asp:Label>
The next is a asp:TextBox:
<asp:TextBox Text='<%# Bind("SubmitDT") %>' runat="server" ID="SubmitDTTextBox" />
Both of these are sitting inside of the asp:FormView with an ID="AddItemFv" which has a DataSourceID="AddInvAsset" (which is irrelevant for this discussion but just provided as supplemental info).
Here is the code behind where my problem is:
namespace CInTrac
{
public partial class AddAsset : System.Web.UI.Page
{
protected void Page_Preload(object sender,EventArgs e)
{
AddInvAsset.SelectParameters.Add("SubmitBy", Session["RegUser"].ToString());
AddInvAsset.SelectParameters.Add("SubmitDT", DateTime.Now.ToString("MM/dd/yyyy"));
}
protected void Page_Load(object sender, EventArgs e)
{
Label uname = (Label)AddItemFv.Row.FindControl("SubmitBy");
if (uname != null)
uname.Text = Session["RegUser"].ToString();
TextBox udate = (TextBox)AddItemFv.Row.FindControl("SubmitDT");
if (udate != null)
udate.Text = DateTime.Now.ToString();
Response.Write("<b>Submitted by should be:</b> = " + Session["RegUser"].ToString() + "<br>");
Response.Write("<b>Submit Date should be:</b> = " + DateTime.Now.ToString("MM/dd/yyyy") + "<br>");
}
}
}
The problem that I'm having is Just what you see in the example above; absolutely nothing! I'm new to C# so I am likely doing something wrong with my code here and in debug my trace indicates that as we check for null it then fails to assign value to .Text of each VAR and therefore our values never show up.
Update:
As IM pointed out I had missed the proper name of the controls in the code. Below are the corrections I made to the code above which works fine. Again THanks to Inquisitive_mind for pointing out my error. :
protected void Page_Load(object sender, EventArgs e)
{
Label uname = (Label)AddItemFv.Row.FindControl("SubmitByLbl");
if (uname != null)
uname.Text = Session["RegUser"].ToString();
TextBox udate = (TextBox)AddItemFv.Row.FindControl("SubmitDTTextBox");
if (udate != null)
udate.Text = DateTime.Now.ToString("MM/dd/yyyy");
}
The ID of the controls is incorrect
Change
Label uname = (Label)AddItemFv.Row.FindControl("SubmitBy");
TextBox udate = (TextBox)AddItemFv.Row.FindControl("SubmitDT");
To
Label uname = (Label)AddItemFv.Row.FindControl("SubmitByLbl");
TextBox udate = (TextBox)AddItemFv.Row.FindControl("SubmitDTTextBox");
EDIT
You will have to move the FindControl to a FormView event.The controls will only be accessible after the FormView has been completely created and databound.Try moving the code from page_load to YourFormView_Databound event.
protected void YourFormView_DataBound(Object sender, EventArgs e)
{
Label uname = (Label)AddItemFv.Row.FindControl("SubmitByLbl");
if (uname != null)
uname.Text = Session["RegUser"].ToString();
TextBox udate = (TextBox)AddItemFv.Row.FindControl("SubmitDTTextBox");
if (udate != null)
udate.Text = DateTime.Now.ToString();
}

webforms : use infragistics webdropdown in updatepanel

For your information (this was my original problem webforms : add dynamically in javascript option to a dropdownlist, solved thanks to ConnorsFan).
My goal is to having a infragistics dropdownlist enabling multi selection and at each selection I want an event fired server side without refreshing the whole page.
This is my aspx page :
<%# Register assembly="Infragistics45.Web.v16.1, Version=16.1.20161.1000, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" namespace="Infragistics.Web.UI.ListControls" tagprefix="ig" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<ig:WebDropDown ID="WebDropDown1" runat="server" Width="200px" OnSelectionChanged="WebDropDown1_SelectionChanged" EnableMultipleSelection="true" EnableClosingDropDownOnSelect="false" AutoPostBack="true">
</ig:WebDropDown>
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlId="WebDropDown1" EventName="SelectionChanged"/>
</Triggers>
</asp:UpdatePanel>
This is my code-behind page :
private List<string> allPossiblechoices = new List<string>() { "a", "b", "c","d","e" };
private List<string> defaultChoices = new List<string>() { "a", "b", "c" };
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
foreach(var choice in allPossiblechoices)
{
WebDropDown1.Items.Add(
new DropDownItem()
{
Text = choice,
Value = choice,
Selected = defaultChoices.Contains(choice)
}
);
}
}
}
protected void WebDropDown1_SelectionChanged(object sender, DropDownSelectionChangedEventArgs e)
{
// I put a breakpoint here to see what e.NewSelection and e.OldSelection are
}
By default, when the page is requested for the first time, the dropdown is composed of a,b,c,d,e and only a,b,c are selected.
When I select d, a request is indeed send to the server (I put a breakpoint in my event handler) and the results are correct :
EventArgs e.OldSelection contains a,b,c.
EventArgs e.NewSelection contains a,b,c,d.
Then, I deselect d and the results are the following :
EventArgs e.OldSelection contains a,b,c.d.
EventArgs e.NewSelection contains a,b,c,d.
I don't understand why EventArgs e.NewSelection contains d even if I deselected it.
The fact that it's even more strange, is that I have done the same thing without the updatePanel and everything works fine, the selection (new and old) are correct.
Thanks in advance for your help.
You can call the RegisterStartupScript static method of the ScriptManager class to add some Javascript code to be executed after the event handler has returned. In the code below, I assume that the ID of the UpdatePanel is UpdatePanel1.
protected void WebDropDown1_SelectionChanged(object sender, DropDownSelectionChangedEventArgs e)
{
WebDropDown wdd = sender as WebDropDown;
string scriptCode = string.Format("document.getElementById('{0}').openDropDown();", wdd.ClientID);
ScriptManager.RegisterStartupScript(UpdatePanel1, UpdatePanel1.GetType(), "WDDScript1", scriptCode, true);
}
If it works, you will probably see the WebDropDown closing/opening when the panel is updated (unfortunately).

Dropdownlist SelectedIndexChanged firing on every postback

I am dynamically adding a custom user control to an update panel. My user control contains two dropdownlists and a textbox. When a control outside of the update panel triggers a postsback, I am re-adding the user control to the update panel.
The problem is...on postback when I re-add the user controls, it's firing the "SelectedIndexChanged" event of the dropdownlists inside the user control. Even if the selectedindex did not change since the last postback.
Any ideas?
I can post the code if necessary, but there's quite a bit in this particular scenario.
Thanks in advance!
EDIT...CODE ADDED BELOW
*.ASCX
<asp:DropDownList ID="ddlColumns" OnSelectedIndexChanged="ddlColumns_SelectedChanged" AppendDataBoundItems="true" AutoPostBack="true" runat="server">
*.ASCX.CS
List<dataColumnSpecs> dataColumns = new List<dataColumnSpecs>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
fillDDLColumns();
}
}
public void fillDataColumnsList()
{
dataColumns.Clear();
//COMMON GETDATATABLE RETURNS A DATA TABLE POPULATED WITH THE RESULTS FROM THE STORED PROC COMMAND
DataTable dt = common.getDataTable(storedProcs.SELECT_COLUMNS, new List<SqlParameter>());
foreach (DataRow dr in dt.Rows)
{
dataColumns.Add(new dataColumnSpecs(dr["columnName"].ToString(), dr["friendlyName"].ToString(), dr["dataType"].ToString(), (int)dr["dataSize"]));
}
}
public void fillDDLColumns()
{
fillDataColumnsList();
ddlColumns.Items.Clear();
foreach (dataColumnSpecs dcs in dataColumns)
{
ListItem li = new ListItem();
li.Text = dcs.friendlyName;
li.Value = dcs.columnName;
ddlColumns.Items.Add(li);
}
ddlColumns.Items.Insert(0, new ListItem(" -SELECT A COLUMN- ", ""));
ddlColumns.DataBind();
}
protected void ddlColumns_SelectedChanged(object sender, EventArgs e)
{
//THIS CODE IS BEING FIRED WHEN A BUTTON ON THE PARENT *.ASPX IS CLICKED
}
*.ASPX
<asp:UpdatePanel ID="upControls" runat="server">
<ContentTemplate>
<asp:Button ID="btnAddControl" runat="server" Text="+" OnClick="btnAddControl_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="btnGo" runat="server" Text="Go" OnClick="btnGo_Click" ValidationGroup="vgGo" />
<asp:GridView...
*.ASPX.CS
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
uc_Counter = 0;
addControl();
gridview_DataBind();
}
else
{
reloadControls();
}
}
protected void btnGo_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//THIS BUTTON CLICK IS WHAT'S TRIGGERING THE
//SELECTEDINDEXCHANGED EVENT TO FIRE ON MY *.ASCX
gridview_DataBind();
}
}
private void reloadControls()
{
int count = this.uc_Counter;
for (int i = 0; i < count; i++)
{
Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
myUserControl.ID = "scID_" + i;
upControls.ContentTemplateContainer.Controls.AddAt(i, myUserControl);
((customUserControl)myUserControl).fillDDLColumns();
}
}
private void addControl()
{
Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
myUserControl.ID = "scID_" + uc_Counter.ToString();
upControls.ContentTemplateContainer.Controls.AddAt(upControls.ContentTemplateContainer.Controls.IndexOf(btnAddControl), myUserControl);
//((customUserControl)myUserControl).fillDDLColumns();
this.uc_Counter++;
}
protected int uc_Counter
{
get { return (int)ViewState["uc_Counter"]; }
set { ViewState["uc_Counter"] = value; }
}
Even though this is already answered I want to put an answer here since I've recently tangled with this problem and I couldn't find an answer anywhere that helped me but I did find a solution after a lot of digging into the code.
For me, the reason why this was happening was due to someone overwriting PageStatePersister to change how the viewstate hidden field is rendered. Why do that? I found my answer here.
One of the greatest problems when trying to optimize an ASP.NET page to be more search engine friendly is the view state hidden field. Most search engines give more score to the content of the firsts[sic] thousands of bytes of the document so if your first 2 KB are view state junk your pages are penalized. So the goal here is to move the view state data as down as possible.
What the code I encountered did was blank out the __VIEWSTATE hidden fields and create a view_state hidden field towards the bottom of the page. The problem with this is that it totally mucked up the viewstate and I was getting dropdownlists reported as being changed when they weren't, as well as having all dropdownlists going through the same handler on submit. It was a mess. My solution was to turn off this custom persister on this page only so I wouldn't have to compensate for all this weirdness.
protected override PageStatePersister PageStatePersister
{
get
{
if (LoginRedirectUrl == "/the_page_in_question.aspx")
{
return new HiddenFieldPageStatePersister(Page);
}
return new CustomPageStatePersister(this);
}
}
This allowed me to have my proper viewstate for the page I needed it on but kept the SEO code for the rest of the site. Hope this helps someone.
I found my answer in this post .net DropDownList gets cleared after postback
I changed my counter that I was storing in the viewstate to a session variable.
Then I moved my reloadControls() function from the Page_Load of the *.ASPX to the Page_Init.
The key was dynamically adding my user control in the Page_Init so it would be a member of the page before the Viewstate was applied to controls on the page.

Disable Postback on button ASP.NET c#

here is an example of what I am doing
Page Load
{
//Adds items to a panel (not an updatepanel just a normal panel control)
}
protected void btnNexMod_Click(object sender, EventArgs e)
{
// Calls DoWork() and Appends more items to the same panel
}
My problem is that the asp:button is doing a postback as well as calling DoWork()
Therefore, re-calling my page load, re-initializing my panel :(
I want my items that I have added to the panel to stay there!
All help appreciated, not looking for a hand you the answer kind-of deal. Any steps are appreciated thanks!
Here is an exact example of my problem.
protected void Page_Load(object sender, EventArgs e)
{
CheckBox chkbox = new CheckBox();
chkbox.Text = "hey";
chkbox.ID = "chk" + "hey";
// Add our checkbox to the panel
Panel1.Controls.Add(chkbox);
}
protected void Button1_Click(object sender, EventArgs e)
{
CheckBox chkbox = new CheckBox();
chkbox.Text = "hey";
chkbox.ID = "chk" + "hey";
// Add our checkbox to the panel
Panel1.Controls.Add(chkbox);
}
Only thing on the page is a empty panel and a button with this click even handler.
I have also tried this and it still doesn't work. Now its clearing the initial item appended to the panel.
if (!Page.IsPostBack) // to avoid reloading your control on postback
{
CheckBox chkbox = new CheckBox();
chkbox.Text = "Initial";
chkbox.ID = "chk" + "Initial";
// Add our checkbox to the panel
Panel1.Controls.Add(chkbox);
}
If you're adding controls to the Panel dynamically, then you'll have to recreate the controls at every postback, and make sure to assign the same IDs to the controls so that ViewState can populate the values. It's usually best to recreate dynamic content during OnInit, but this can be difficult in some situations.
One of my favorite tools is the DynamicControlsPlaceHolder, because you can add dynamic controls to it and it will persist them automagically, without any additional coding required on the page. Just add controls to it, and it will do the rest.
Here's the link:
http://www.denisbauer.com/Home/DynamicControlsPlaceholder
As for preventing your button from performing a postback, use OnClientClick and return false.
OnClientClick="return false;"
You could use
<asp:LinkButton OnClientClick="javascript:addItemsToPanel();return false;"
thus using a javascript function to add them. That's how I've got around that problem.
You can also try this:
Page Load
{
if (!this.IsPostBack) // to avoid reloading your control on postback
{
//Adds items to a panel (not an updatepanel just a normal panel control)
}
}
you can do like this...
ASPX code:
<asp:LinkButton ID="someID" runat="server" Text="clicky"></asp:LinkButton>
Code behind:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
someID.Attributes.Add("onClick", "return false;");
}
}
What renders as HTML is:
<a onclick="return false;" id="someID" href="javascript:__doPostBack('someID','')">clicky</a>
You are correct, you will have to add the new items to the Panel after a PostBack. That is the nature of the .NET pipeline.
If you use a data bound control, like a Repeater, to display the panel contents, then the button click handler just needs to rebind the control and it will all work out correctly.
Changing the asp:Button to a asp:LinkButton solved my issue.
I think, it is better use the Ajax Update panel. And put your button in to that.
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button1" />
</ContentTemplate>
</asp:UpdatePanel>

Categories

Resources