Dynamically created content is updating "a step behind" on button click - c#

So I am creating a simple question/answer format and having an issue when submitting an answer. I dynamically create divs/buttons/textboxs from the database via a "RenderQuestions()" function. This creates a list of questions and answer textbox/buttons. When attempting to answer a question, I type my answer click submit and nothing happens. I do it again and it shows my first answer. It's a "step behind".. If I refresh it then shows all answers as it should. I've been struggling with this all night. Here's some code:
-----My page load----- (Relevant parts)
protected void Page_Load(object sender, EventArgs e)
{
//If authenticated hide login & show welcome bloc
if (User.Identity.IsAuthenticated)
{
//Show question & render
questionsBloc.Visible = true;
//if(Page.IsPostBack)
RenderQuestions();
}
-----RenderQuestions() function---- (The relevant parts)
//Initialize & get answers
List<Answer> answers = new List<Answer>();
answers = um.GetAnswers(q.QuestionID);
//Initialize html render
HtmlGenericControl questionDiv = new HtmlGenericControl("div");
TextBox txtAnswer = new TextBox();
Button btnAnswer = new Button();
//Set Answer Button
btnAnswer.Text = "Answer";
btnAnswer.Click += new EventHandler(btnAnswer_Click);
//Set ID's
btnAnswer.ID = "btnAnswer" + q.QuestionID.ToString();
questionDiv.ID = "questionDiv" + q.QuestionID.ToString();
//Set classes
questionDiv.Attributes.Add("class", "questionBloc");
btnAnswer.CausesValidation = false;
btnAnswer.EnableViewState = false;
//btnAnswer.UseSubmitBehavior = true;
//Fill inner text with question
questionDiv.InnerText = q.QuestionContent; //Insert question..
//actionDiv.InnerText = "Like/Dislike/Comment/Flag"; //Insert answer..
//Add answer textbox and button to action div
actionDiv.Controls.Add(btnAnswer);
//Add question div to qaDiv
qaDiv.Controls.Add(questionDiv);
//Add action div to qaDiv
qaDiv.Controls.Add(actionDiv);
//Add all controls to feedbloc
feedBloc.Controls.Add(qaDiv);
-----My btnAnswer event handler -----
private void btnAnswer_Click(object sender, EventArgs e)
{
UserManager um = new UserManager();
um.PostAnswer("My first answer!");
//RenderGlobalFeed();
}
That's every reference to my button.. Should I be initializing the btn click event in my page_init? Any help is much appreciated.
Thanks guys

Set AutoPostBack=true on btnAnswer. It's not triggering the server to act on the button click.

If you want to get event btnAnswer_Click triggered , then you must render the same Content and assign the eventHandler in every pageload(ie; the page load after the client button click must render the button again and EventHandler must be assigned).
Asp.net won't trigger the event if it doesn't find the controls in the pageload. Remember, after clicking a button, the page load event triggers first and then only the Click_event will be triggered.
The RenderQuestions() must be called in the btnAnswer_Click Event too. This will avoid the a step back problem.
In this scenario I would recommend you to learn about ajax (using jQuery library) requests in asp.net (using WebMethods or webservices) to avoid these postbacks.

Related

If I cannot use C# to respond in realtime to radio button CheckedChanged events in Sharepoint, how can I add client-side (jQuery) code to do it?

I posed a similar question about this before, and it would seem based on the answers that I received that I can't expect to be able to rely on a radio button's CheckedChanged event to fire in real time.
Am I really stuck with waiting until the form is submitted before that event fires, or can I add client-side (jQuery) code to handle it? If so, how? How can I mix jQuery client code in with my C# server code in a Sharepoint (2010) project?
What I want to be able to do now is to dynamically alter the controls on the page based on decisions made by the user (if they select this radio button, a particular textbox has this set of properties applied, and if the other radio button, a different set of properties). Is this possible?
UPDATE
I create controls and add CheckedChanged events to them like so:
rbUSCitizenOrPermResY = new RadioButton
{
CssClass = "finaff-webform-field-input"//,
//CheckedChanged += new EventHandler(rbUSCitizenOrPermResY_Changed) <= the name 'CheckedChanged' does not exist in the current context
};
rbUSCitizenOrPermResY.CheckedChanged += new EventHandler(rbUSCitizenOrPermResY_Changed);
cellRadioButton1_1.Controls.Add(rbUSCitizenOrPermResY);
The Save button is like so:
Button btnSave = new Button();
btnSave.Text = "Save";
btnSave.Click += new EventHandler(btnSave_Click);
this.Controls.Add(btnSave);
. . .
private void btnSave_Click(object sender, EventArgs e)
{
LiteralControl message = null;
try
{
message = new LiteralControl();
Controls.Add(message);
ConditionallyCreateList();
SaveInputToList();
List<ListColumns> listOfListItems = ReadFromList();
GeneratePDF(listOfListItems);
message.Text = "Saving the data and converting it to a PDF has been successful";
}
catch (Exception ex)
{
message.Text = String.Format("Exception occurred: {0}", ex.Message);
}
}
What is special about the Save button that it fires immediatley when clicked, yet the CheckedChanged event of a RadioButton does not fire (immediately)?
UPDATE 2
This says, "...UpdatePanel control ... by default, this control does not work with these standard SharePoint components..."
So it sounds like using it is trying to shoehorn a lumberjack's foot into a baby booty.
Then what is the preferred method for getting Sharepoint components to update?
UPDATE 3
Theoretically, it seems maybe this will work:
UpdatePanel up = new UpdatePanel();
up.Controls.Add(dynamicTable); // or just add the radio buttons, rather than the entire HtmlTable?
ScriptManager sm = new ScriptManager();
sm.EnablePartialRendering = true;
...I'll find out, I reckon...

ASP .net PostBack and Function

I'm working on a web page,
I need that when it loads first time it would get data from api's.
Then I want to go from page to page with the same data.
I used IsPostBack
Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//First Time Load Data
leadsList = new List<Lead>();
var client = TVPLeads.Session.GetWebClient(Session);
string PostId = PostId = Request.QueryString["postId"];
PostId = "1";
try
{
leadsList = API.GetPostLeads(client, PostId);
}
catch (Exception) { }
page = (page == 0) ? 0 : page - 1;
DisplayLeadsPage(leadsList, page, "");
}
}
private void pageChoosen(object sender, EventArgs e)
{
int page = int.Parse(((Button)sender).CommandArgument);
DisplayLeadsPage(leadsList, page-1, "");
}
DisplayPagination(){
.
.
Button prev = new Button{
ID = "page_"+i,
CssClass = "Pagination",
Text = "i",
CommandArgument = ""+i,
OnClientClick = "pageChoosen"
};
prev.Click += pageChoosen;
divPagination.Controls.Add(prev);
.
.
.
}
I clicking on a button , got to Page_Load function the postBack is true as expected , but the function is not firing(checked with debugger).
if I remove the IsPostBack and it would make all over again , then the button function is firing.
What's the problem with that? How to use it right ?
The first time you request your page, your page is not posted back. The rendering engine of asp.net creates the page and sends it back to the client.
When you click a button then this click we trigger a postback and a handler that is defined the Page class will execute some code. Then the page will be build and when on Page_Load comes into the scene, the code that is in the if(!Page.IsPostBack) will not be executed, because the IsPostBack property of the Page class is true.
There are two key concepts to conceive there. The first is about the Page lifecycle, the events that the page goes through in each request.
The second is that the Page is not posted back only the first time the client requests it (or the times that she does a full refresh of the page, clicking F5 for instance in Chrome).
Update
Respond to button click
If you haven't defined a server side button, you should define one. How?
In you markup, just add the following line of code:
<asp:Button id="buttonId" Text="Submit" runat="server" />
Then in the designer double click on the button. As you will notice, you will be navigated to the code behind class and a method would have been created, which would be the click handler. Then inside the body of this method, you could write the commands that should be executed, when the user clicks on your button. If you now go back to your markup, you will notice the another attribute would have been added to the Button with name OnClick.
Update
Dynamically built buttons need to be created again when the page is posting back. Otherwise they won't work.
Try adding an event handler to the control.
Your control will look something like this (on the aspx page):
<asp:button id="YourButton" runat="server" OnClick="YourButton_Click" />
Then your backend handler should also be public:
public void YourButton_Click(object sender, System.EventArgs e) {
Edit: You can also do this:
leadsList = new List<Lead>();
if (!Page.IsPostBack)
{
...
}
else
{
page = (page == 0) ? 0 : page - 1;
DisplayLeadsPage(leadsList, page, "");
}
Found an answer for the problem.
When the page is posted back to server.
I need to rebuild the controls Otherwise, those controls will be null.

Postback from Dynamic Content

I am dynamically building some HTML content on a WebForms page, using HtmlGenericControl().
HtmlGenericControl p = new HtmlGenericControl("p");
// ...
ListItems.Controls.Add(p);
But now I need to add a button to the paragraph created above, and the button needs to do a postback when clicked.
Must I completely rework this code to load child controls, which can contain real server-side buttons? Or is there a way to inject buttons capable of some type of postback?
Here's a test method and test EventHandler that, if called, will add a button control with a server-side Click event to ListItems. The commented-out code will change the markup of the ListItems object if InnerHtml is available but I rethought that approach and assumed the existence of a textbox on the page that would show the results of the click event firing. There are a number of concerns that you'll want to handle if you need those child controls to be present from one postback to another, though- for instance, if Test() isn't called every time the page loads that button won't be created and there will be no way to call its EventHandler unless other controls also call it.
public void Test()
{
System.Web.UI.HtmlControls.HtmlGenericControl p = new System.Web.UI.HtmlControls.HtmlGenericControl("p");
p.InnerHtml = #"<strong>Test</strong>";
// ...
ListItems.Controls.Add(p);
Button b = new Button();
b.ID = "cmdTest";
b.Text = "Test";
b.Click += new EventHandler(test_Click);
p.Controls.Add(b);
}
protected void test_Click(object sender, EventArgs e)
{
// ListItems.InnerHtml = "Test button clicked";
txtTestResults.Text = "Test button clicked at " + DateTime.Now.ToShortTimeString();
}

Why is my Linkbuttons command function not getting trigged?

I have this code in my codebehind:
for (int i = 0; i < linkList.Count; i++)
{
var link = UppercaseFirst(linkList[i]);
var linkButton = new LinkButton
{
Text = link + " > ",
ID = Convert.ToString(i),
CommandArgument = urlList[i]
};
linkButton.Command += new CommandEventHandler(lnkWeb_Click);
bcHolder.Controls.Add(linkButton);
}
and here is the lnkWeb_Click method:
protected void lnkWeb_Click(object sender, CommandEventArgs e)
{
var url = e.CommandArgument.ToString();
//code...
}
This method is not getting triggered when I click on one of those generated linkbuttons.
Anyone have any idea what the problem is?
Tried OnCommand="lnkWeb_Click" in the aspx file and the method got trigged, but not those that I generate by code. They dont even have OnCommand="lnkWeb_Click" attribute.
The problem here is with the control life cycle. If you want to handle events of some control properly - you have to add this control to the page on every page loading process, that is on every postback.
Look what happens in your case:
Initial button is clicked
During the post back your dynamic link buttons are added to the page, event handlers are assigned to them
User clicks on the newly generated link button
During post back these dynamic link buttons are not added to the page again, ASP.NET does not know the origin of a event so it does not call the handler.
To fix this you might need to store in the View State information about link buttons that have to be added (please do not store the controls themselves, that would be a huge overhead). Also pay attention to their IDs - they have to be the same for the same controls.
Update. Some more hints on the View State solution.
Basically you need some indicator that during the page loading you need to create some dynamic link buttons. The very basic way to do it is to store the list of the link button identifiers (or texts, or both) and then during Page_Load check if there is anything stored in View State. For example:
// Property to access the view state data
protected List<string> Links
{
get { return ViewState['links']; }
set { ViewState['links'] = value; }
}
...
protected void Page_Load(object sender, EventArgs e)
{
...
if (this.Links != null && this.Links.Count > 0)
{
// inside this method you create your link buttons and add them to the page
// you actually have this code already
RenderLinkButtons();
}
}
...
// Not sure about what name you have here
protected void InitialButtonHandlerName(object sender, EventArgs e)
{
List<string> linkList = ...; //your variable, guessing a type
// this is exactly the method you use already to add links to the page
// just one more action added to it - store info about these links into View State to use it on later post backs
this.Links = linkList;
RenderLinkButtons();
}
Please use it just a point in right direction - you might have different implementation depending on your requirements and preferences. But I hope concept is clear now.

ASP.NET Button click redirect to new page

I have created a Button programmatically.
I now want to redirect to a new aspx page on the click of this Button, such that we will enter into one of the methods of the new page (like page_load(), etc.)
Is this possible?
Eg:
Button oButton = new Button;
oButton.Text = "NextPage";
// Redirect to "Redirect.aspx" on click
But I am not able to find an entry point in Redirect.aspx where I can do some changes to the UI components once we get redirected to "Redirect.aspx"
Regards,
Parag
You need to handle Click event of oButton.
Button oButton = new Button();
oButton.Text = "NextPage";
oButton.Click += (sa, ea) =>
{
Response.Redirect("Redirect.aspx");
};
You can use query string parameters and depending on the value of param call the appropriate method in Page_Load of Redirect.aspx
e.g.
Redirect.aspx?val=1
in Redirect.aspx
protected void Page_Load(...){
string var = Request.QueryString["val"];
if(var == "1")
some_method();
else
some_other_method();
}
You could also use the PostBackUrl property of the Button - this will post to the page specified, and if you need to access items from the previous page you can use the PreviousPage property:
Button oButton = new Button;
oButton.Text = "NextPage";
oButton.PostBackUrl = "Redirect.aspx";
Then in you wanted to get the value from, say, a TextBox on the previous page with an id of txtMyInput, you could do this (very simple example to give you an idea):
void Page_Load(object sender, EventArgs e)
{
string myInputText = ((TextBox)PreviousPage.FindControl("txtMyInput")).Text;
// Do something with/based on the value.
}
Just another example of how to accomplish what I think you're asking.
See Button.PostBackUrl Property for more info.

Categories