i got a page where the admin can edit some photos i pull from flickr so all the controls are added Dynamiclly.
i have few controls i add to a panel and then add the panel to Form.Controls.
all the data thay are holding come from flickr.
my problem is that, afther a post back the list change and the controls are loading, BUT the Text Box's keep that same data befor the post back even though i get the data from flickr every time.
what wierd for my that if i do this with less textbox every thing work fine.
the list are about 10+ pictures and this numbers can change in the future.
(sorry for the messy code im pretty new to programming)
here is the code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
RadioButtonList1.AutoPostBack = true;
selectedSetID = getSelectedSetId(RadioButtonList1.SelectedItem.Text);
photoSet = new MyPhotoSet(selectedSetID);
photo = new FlickerImages[photoSet.Count];
for (int j = 0; j < photo.Length; j++)
{
photo[j] = new FlickerImages(photoSet.MediumURLS[j], photoSet.ThumbnailURLS[j], photoSet.Titles[j], photoSet.Descreption[j], photoSet.PhotosID[j]);
panel = photo[j].GetPanelWithEditControls(j);
button = new Button();
button.ID = "sendDataButton" + j;
button.Text = "send data";
button.Click += button_Click;
panel.Controls.Add(button);
Form.Controls.Add(panel);
}
}
else
{
//here is the post back,
every thing load fine.
adding and removing the controls but if the textbox's load in the same place, it hold the same data befor the post back.
RadioButtonList1.AutoPostBack = true;
selectedSetID = getSelectedSetId(RadioButtonList1.SelectedItem.Text);
photoSet = new MyPhotoSet(selectedSetID);
photo = new FlickerImages[photoSet.Count];
for (int i = 0; i < photo.Length; i++)
{
photo[i] = new FlickerImages(photoSet.MediumURLS[i], photoSet.ThumbnailURLS[i], photoSet.Titles[i], photoSet.Descreption[i], photoSet.PhotosID[i]);
panel = photo[i].GetPanelWithEditControls(i);
button = new Button();
button.ID = "sendDataButton" + i;
button.Text = "send data";
button.Click += button_Click;
panel.Controls.Add(button);
Form.Controls.Add(panel);
}
}
}
(sorry for my english)
Instead of putting your control generation in Page_Load, put it in Page_Init.
Since you mentioned that you're pretty new to ASP.NET, I strongly recommend reading up on the Page Lifecycle.
As an ASP.NET developer, it's very important that you understand how and when certain things happen on the server in between the time the server receives a request for an aspx page, and the time the page is output to be rendered by the browser.
The short explanation for why I suggest putting the code in Page_Init is how the runtime deals with dynamically created controls and Viewstate. The Viewstate contains any changes made by the user of your web app. In the page lifecycle, you'll notice that the application of Viewstate values happen before Page_Load, but after Page_Init.
This means that if your code in in Page_Load, then the controls are generated from Viewstate, updated with what the user put in, but then your own code in page_Load is re-generating those controls with the default values. There's nothing that happens after this event that can re-load the user's input.
(Hopefully that makes sense. If not, the page I linked to may explain it better.)
There's another article on here that addresses the subject from a different angle, but still should be very helpful for you.
And there's the ultra-short version here.
And finally, (saving the best for last) one of the most comprehensive articles on the subject that explains things in plain English can be found here.
Related
ASP.NET 4.7.2 Web Forms c# VS 2019
I am trying to use a modalpopupextender to prompt for new data for foreign key fields. Like the form itself, the MPE is built on the fly in code -- in this case the click handler for the hidden button that the Javascript fires off to build and show the MPE.
I read every single article on SO and the ASP forums and tried everything I saw there. No joy. I get the popup perfectly. Hitting OK closes the popup, but never fires the OK Event.
Here is the code:
//Building the form, we do this in OnInit:
// AJAX Update Panel
UpdatePanel PUP = new UpdatePanel()
{
ID = "PUP",
};
PlaceHolder.Controls.Add(PUP);
// HiddenField containing the field name to permit
// creating the correct modalpopup.
HiddenField HFPopupField = new HiddenField()
{
ID = "HF_POPUP"
};
PUP.ContentTemplateContainer.Controls.Add(HFPopupField);
// Create Hidden button to track the popup
Button BPopup = new Button()
{
ID = "BPOPUP",
UseSubmitBehavior = false
};
BPopup.Click += BPopup_Click;
BPopup.Attributes.Add("style", "display: none;");
PUP.ContentTemplateContainer.Controls.Add(BPopup);
// And create the background panel for the popup.
Panel PnlPopup = new Panel()
{
ID = "PNLPOPUP",
CssClass = "MpeBackground"
};
PnlPopup.Attributes.Add("style", "display: none;");
PUP.ContentTemplateContainer.Controls.Add(PnlPopup);
/// Event handler for hidden button.
protected void BPopup_Click(object sender, EventArgs e)
{
[snip -- code to get the dataset that is being filled]
UpdatePanel PUP = Placeholder.FindControlRecursive("PUP");
Table T = new Table()
{
CssClass = "PopupTbl"
};
TableRow TRTitle = new TableRow();
TableCell TCTitle = new TableCell()
{
CssClass = "PopupTitle",
ColumnSpan = 2
};
Label LPopTitle = new Label()
{
Text = [title of the popup]
};
TCTitle.Controls.Add(LPopTitle);
TRTitle.Cells.Add(TCTitle);
DataRow drData = null;
// Add Fields, and also the cancel and Add buttons
foreach (DataColumn DC in dsColumns.Tables[0].Columns)
{
TableRow TRColumn = [create a tablerow with 2 columns, a prompt and the input field]
if (TRColumn != null)
{
T.Rows.Add(TRColumn);
[snip]
}
} // end of foreach(DataColumn DC in dsColumns.Tables[0].Columns)
PnlWindow.Controls.Add(T);
TableRow TRButtons = new TableRow();
TableCell TCButtons = new TableCell()
{
ColumnSpan = 2,
CssClass="PopupButtons"
};
Button MPEBOK = new Button()
{
ID = "MPE" + sFieldName + "_MPEBOK",
Text = "OK",
CausesValidation = false,
UseSubmitBehavior = false
};
MPEBOK.Click += MPEBOK_Clicked;
TCButtons.Controls.Add(MPEBOK);
LiteralControl LCB = new LiteralControl()
{
Text = " "
};
TCButtons.Controls.Add(LCB);
//************************************************************
//*** Postback Trigger ***
//************************************************************
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger()
{
ControlID = MPEBOK.ID,
EventName = "click"
};
PUP.Triggers.Add(trigger);
//************************************************************
//*** Cancel Button ***
//************************************************************
Button MPEBuhBye = new Button()
{
ID = "MPE" + sFieldName + "_BUHBYE",
Text = "Cancel",
UseSubmitBehavior = false
};
TCButtons.Controls.Add(MPEBuhBye);
TRButtons.Cells.Add(TCButtons);
T.Rows.Add(TRButtons);
PnlPopup.Controls.Add(PnlWindow);
AjaxControlToolkit.ModalPopupExtender MPE = new AjaxControlToolkit.ModalPopupExtender()
{
ID = "MPE" + sFieldName,
PopupControlID = "PNLPOPUP",
TargetControlID = "BPOPUP",
BackgroundCssClass = "MpeBackground"
};
// Add the MPE to the UpdatePanel.
PUP.ContentTemplateContainer.Controls.Add(MPE);
// Show the modal popup extender.
MPE.Show();
}
protected void MPEBOK_Clicked(object sender, EventArgs e)
{
[snip - this never fires]
}
I cannot find out what is happening here. Can anyone see something hinky?
Thanks
John.
You can't add a server side button or inject a server side button into the page DOM.
When you drag a asp.net button onto the form, BOTH the "mypage.cs" and mypage.desinger.cs ARE updated. The wire up of the button occurs at design time, and you would have to modify mypage.desinger.cs ALSO and ADD a button event stub.
So you can't do this.
A compromise would be to also add some js and have that HTML button execute a .click() method of a hidden asp.net button you drop into that page (that would give you the post back, and the running behind of a separate button event code stub.
This event resolution occurs at compile time - not at page render time. You have to drop that button onto the page.
I suppose you could adopt a standard that you always place right below that "div" on the page the button (hidden with style=none. And then as noted, have your injected code along with some js execute a click on the hidden button. Or just have the js button code execute a __doPostback("some value") and pick this up in the page on-load event, and then call the routine (function) from on-page load event.
I think better would be to use a jQuery.UI dialog, as that dialog CAN say load + use another different web page into a “div” on the existing page. So you layout, make, and create the nice looking popup form as a separate web page. jQuery is able to remove the “form” and additonal tags out of that page load, and then inject it into the existing page. (that code would be rather hard to re-produce). so jQuery.UI is able to pop up that separate page. however, the buttons on that loaded page (into that div) of course can't really run any code behind in the current page. However, the buttons CAN run local js in the current page. Thus the actions of this injected page would be local to each page. But the popup would not be directly calling a code behind stub.
Now, to adopt jQuery.UI, then you also have to of course adopt jQuery. So that is two extra libraries you need. (but, jQuery you likely already have).
However, I suppose the whole point of using the ajax toolkit is to avoid jQuery.ui in the first place. To be fair, before jQuery.ui came along, that tool kit was REALLY impressive, and gave asp.net folks a REAL leg up on the competition. (and it tends to be MUCH less wiring up then say using jQuery.UI
So the AjaxToolkit in its heyday was impressive. Now, it of course showing its age, but I still use the kit, and this is especially the case for the AjaxFileUploader. And yes I do use the popups – even to this day. However, I find now that jQuery.UI dialogs are more flexible, and would be better in this case (because you want a on-the fly setup).
Also, having code behind buttons in even the jQuery.UI dialog, or in this case the ajax popup? Well, only the action button can run code behind. The cancel button of course will just dismiss the dialog. However, any button in the dialog that WILL run code behind? Well, that's ok, since you have a page post back, and it actually the page postback that BLOWS out the dialog anyway.
so i have an HTML table with dynamically added rows and ASP.NET text boxes. I have the rows and controls re-instantiated on page_load if the viewstate[dataonpage] = true, and I'm declaring it as true in the method that adds the rows and controls. (I need them to persist on other postbacks)
The problem is that I'm now I've added a CLEAR button that removes all of the html rows (excluding the headers) when it's clicked, and for some reason on button click it gets an index error, or if using Try/Catch it only removes half of the rows (every other row). I believe the problem is something to do with that the viewstate[dataonpage] is still "true", and the data is being re-added on page load. If i add viewstate["dataonpage"] = "false" into the clear button method, the same happens but at least this way on the second click it removes the second half of the rows.
I understand this happens because the button event handler isn't fired until after the page_load which is why it doesn't work on the first click. But what I don't fully understand is why even without this my clear button code doesn't clear all of the rows in the first place.
Any help on understanding why it doesn't work, and a work around will be greatly appreciated!
protected void Page_Load(object sender, EventArgs e)
{
if (Convert.ToString(ViewState["DataOnPage"]) == "true")
{
Getmarketdata();
}
}
protected void Getdatabtn_Click(object sender, EventArgs e)
{
ViewState["DataOnPage"] = "true";
Getmarketdata();
}
Below is method that creates adds table rows and controls:
public void Getmarketdata()
{
String url = "https://api.rightmove.co.uk/api/rent/find?index=0&sortType=1&maxDaysSinceAdded=" + Dayssinceuploadtext.Text + "&locationIdentifier=OUTCODE%5e" + Outcodetext.Text + "&apiApplication=IPAD";
Response.Write(url);
using (var webclient = new WebClient())
{
String Rawjson = webclient.DownloadString(url);
ViewState["VSMarketDataJSONString"] = Rawjson;
dynamic dobj = JsonConvert.DeserializeObject<dynamic>(Rawjson);
int NoOfHouses = dobj["properties"].Count;
Response.Write("<br />" + NoOfHouses);
for (int i = 0; i < NoOfHouses; i++)
{
System.Web.UI.HtmlControls.HtmlTableRow tRow = new System.Web.UI.HtmlControls.HtmlTableRow();
GeneratorTable.Rows.Add(tRow);
String RMlink = String.Format("https://www.rightmove.co.uk/property-to-rent/property-" + dobj["properties"][i]["identifier"].ToString()) + ".html";
HyperLink hypLink = new HyperLink();
hypLink.Text = dobj["properties"][i]["identifier"].ToString();
hypLink.Target = "_blank";
hypLink.NavigateUrl = RMlink;
using (System.Web.UI.HtmlControls.HtmlTableCell tb1 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
tRow.Cells.Add(tb1);
tb1.Controls.Add(hypLink);
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb2 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCe = new TextBox();
tRow.Cells.Add(tb2);
tb2.Controls.Add(tbEPCe);
String txtboxID = (("EPCETxtBox") + i);
tbEPCe.ID = txtboxID;
tbEPCe.Style.Add("background", "none"); tbEPCe.Style.Add("border", "1px solid black"); tbEPCe.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb3 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCp = new TextBox();
tRow.Cells.Add(tb3);
tb3.Controls.Add(tbEPCp);
String txtboxID = (("EPCPTxtBox") + i);
tbEPCp.ID = txtboxID;
tbEPCp.Style.Add("background", "none"); tbEPCp.Style.Add("border", "1px solid black"); tbEPCp.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb4 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbBbl = new TextBox();
tRow.Cells.Add(tb4);
tb4.Controls.Add(tbBbl);
String txtboxID = (("BblTxtBox") + i);
tbBbl.ID = txtboxID;
tbBbl.Style.Add("background", "none"); tbBbl.Style.Add("border", "1px solid black"); tbBbl.Style.Add("border-radius", "2px");
}
}
}
}
Below is clear table rows method: (this is the one that isn't working)
public void ClearTableRows()
{
System.Web.UI.HtmlControls.HtmlTable Htmlgeneratortable = ((System.Web.UI.HtmlControls.HtmlTable)GeneratorTable);
int NoOfRows = Htmlgeneratortable.Rows.Count;
for (int j = 1; j < NoOfRows; j++)
{
try
{
Htmlgeneratortable.Rows.RemoveAt(j);
}
catch
{ }
}
}
I'm going to explain what's going on as you have the code written now; I don't have faith in my ability to provide an answer including the exact code changes to be made, so here is what is wrong with your current approach:
Your table, GeneratorTable exists for all clients. That doesn't mean every time someone navigates to your website a table is generated, it means that there is one table, and every client that logs in is getting that one table.
So if you add rows to it for one client, then send the table to another client, both clients will see the same table (with the rows added).
The problem is that emptying out a table is logic that has nothing to do with your back-end server. There's no reason for your server to be handling emptying a table, your server should only handle page navigations and AJAX calls pretty much, it shouldn't be changing how the webpage looks, because the server can only respond to each client one time.
What's the point in responding to a client with GeneratorTable and then updating GeneratorTable on the server? The client will never see the updates made to the table unless they're resent from the server.
You stated that you are new to this and need to learn about JS and client-side, this exercise should serve as an example of why you need to put certain code on the front-end and some code on the back-end, as there isn't really an elegeant way to do what you're looking to do with just the server.
I have been working with Web Forms for a short while now and I have read most of what I have found about this on google. However, I am still unclear on how to work with this properly. I like the picture in this answer, but find it a bit too generic. I have not found one decent, concrete example on how to work with these events.
I am currently creating several controls dynamically in code behind in the Page_Load event:
foreach (Service service in Services)
{
// service div
HtmlGenericControl serviceDiv = new HtmlGenericControl("div");
serviceDiv.ID = service.ID;
serviceDiv.Style.Add(HtmlTextWriterStyle.TextAlign, "center");
outerDiv.Controls.Add(serviceDiv); //outerDiv exists in the aspx page
// service updatepanel
UpdatePanel uPanel = new UpdatePanel()
{
ID = service.ID + "_uPanel",
UpdateMode = UpdatePanelUpdateMode.Conditional
};
serviceDiv.Controls.Add(uPanel);
// status span
HtmlGenericControl statusSpan = new HtmlGenericControl("span");
statusSpan.ID = service.ID + "_statusSpan";
statusSpan.InnerHtml = service.Status;
uPanel.ContentTemplateContainer.Controls.Add(statusSpan);
// show specific content
if (service.Status.Equals(ServiceControllerStatus.Running.ToString()))
{
// status color
statusSpan.Attributes.Add("class", "status-run");
// stop button
HtmlButton stopButton = new HtmlButton();
stopButton.ID = service.ID + "_btnStop";
stopButton.InnerHtml = "<i class=\"fa fa-stop btn-red\"/></i>";
stopButton.Attributes.Add("type", "button");
stopButton.Attributes.Add("runat", "server");
stopButton.Attributes.Add("class", "btn btn-link btn-xs");
stopButton.Attributes.Add("title", "Stop");
stopButton.ServerClick += new EventHandler(BtnStop_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(stopButton);
uPanel.ContentTemplateContainer.Controls.Add(stopButton);
// restart button
HtmlButton restartButton = new HtmlButton();
restartButton.ID = service.ID + "_btnRestart";
restartButton.InnerHtml = "<i class=\"fa fa-refresh btn-blue\"/></i>";
restartButton.Attributes.Add("type", "button");
restartButton.Attributes.Add("runat", "server");
restartButton.Attributes.Add("class", "btn btn-link btn-xs");
restartButton.Attributes.Add("title", "Restart");
restartButton.ServerClick += new EventHandler(BtnRestart_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(restartButton);
uPanel.ContentTemplateContainer.Controls.Add(restartButton);
}
else
{
// status color
statusSpan.Attributes.Add("class", "status-stop");
// start button
HtmlButton startButton = new HtmlButton();
startButton.ID = service.ID + "_btnStart";
startButton.InnerHtml = "<i class=\"fa fa-play btn-green\"/></i>";
startButton.Attributes.Add("type", "button");
startButton.Attributes.Add("runat", "server");
startButton.Attributes.Add("class", "btn btn-link btn-xs");
startButton.Attributes.Add("title", "Start");
startButton.ServerClick += new EventHandler(BtnStart_Click);
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(startButton);
uPanel.ContentTemplateContainer.Controls.Add(startButton);
}
// version span
HtmlGenericControl versionSpan = new HtmlGenericControl("span");
versionSpan.ID = service.ID + "_version";
versionSpan.InnerHtml = service.Version;
versionSpan.Attributes.Add("class", "version-text");
serviceDiv.Controls.Add(versionSpan);
What would I gain from creating these in Page_Init? If I create them in Page_Init, how do I access them in Page_Load? Private global lists of UpdatePanels and HtmlButtons feels so unclean.
I know that the ViewState loads between Page_Init and Page_Load, but what does that really mean? Since I don't do full postbacks, but instead use RegisterAsyncPostBackControl to only update the UpdatePanel's on postback, don't I need to re-populate in Page_Load?
If you don't need the ViewState, then you can also create the controls in Page_Load. The ViewState is used to store the values of the controls (which ones depends on the control) and to use them when the PostBack is sent to the server.
For instance, if you have a textbox, the PostBack contains the new value of the textbox and also the old value in the ViewState. The ASP.NET framework now compares those two and raises the TextChanged event if necessary. Without ViewState, this would not be possible.
The best advice you can give regarding dynamically created controls in ASP.NET WebForms is to avoid using them. They increase complexity very fast und are usually not necessary (even if it seems so at first).
In the majority of the cases, there is a much simpler approach, e.g. by using a Repeater. In your case, you have a list of services. You can bind this list to a Repeater and by that avoid to create the controls manually. See this link on how to use a Repeater.
Another upside of using a Repeater is that you can define the UI in the ASPX markup instead of in the code behind file. In your example, you change the UI based upon the status of the service. In this case, using the ItemDataBound-event of the Repeater might be a good option.
I've got a problem with adding some controls into a Panel(which gets "PopUpped" by a ModalPopupExtender) and add a CheckedChanged-EventHandler.
First of all, when user clicks on a button, this happens inside the CreatePanelChoose() function:
foreach (ListItem item in lbSupplier.Items)
{
string cbid = "cb" + i;
CheckBox cb = new CheckBox();
cb.ID = cbid;
cb.Text = item.Text;
cb.AutoPostBack = true;
AjaxControlToolkit.MutuallyExclusiveCheckBoxExtender mecbe = new AjaxControlToolkit.MutuallyExclusiveCheckBoxExtender();
mecbe.ID = "mecbe" + cbid;
mecbe.TargetControlID = cbid;
mecbe.Key = "SupplierKEY";
mecbe.BehaviorID = mecbe.ID + i;
//Also adding a Label
phModalPopupExtender.Controls.Add(new LiteralControl("</br>")); //phModalPopupExtender is a PlaceHolder
phModalPopupExtender.Controls.Add(cb);
phModalPopupExtender.Controls.Add(mecbe);
phModalPopupExtender.Controls.Add(lbl);
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = cbid;
trigger.EventName = "CheckedChanged";
UpdatePanelMatrix.Triggers.Add(trigger);
i++;
ButtonOK.Enabled = false;
}
lblText.Text = "Select one Supplier";
ModalPopupExtender1.Show();
Then i add the EventHandler in the Page_LoadComplete:
As you can see it also gets asigned to the control (I think).
The ModalPopup shows up correctly, but if I click one of the CheckBox, then it just closes it without going into cb_CheckedChanged, but it makes a Async postback ...
If I check Request.Form["__ASYNCPOST"] its true and Request.Form["__EVENTTARGET"] is also correct. (It gives me the unique id!)
Request.Form["__EVENTARGUMENT"] is empty.
I think I also need to say that I use a masterpage.
The problem shouldn't be the lifecycle of the page, because msdn says:
LoadComplete
Raised at the end of the event-handling stage.
Use this event for tasks that require that all other controls on the page be loaded.
Its the onliest place it makes me think it would be right.
Btw: yes i looked trough the topics here allready, but nothing helped me ... (google fo sure also)
Edit 1:
if (IsPostBack)
{
if (recreating == true)
{
CreatePanelChoose();
}
}
In CreatePanelChoose i do the foreach now everytime when its a postback! But it still doesnt fire cb_ChangedChecked ...
Edit 2:
MSDN-Page-Lifecycle also says:
PreInit
Raised after the start stage is complete and before the initialization
stage begins.
Use this event for the following:
Create or re-create dynamic controls.
So i tried to recreate the Panel there. But i dont have the ListItems there to get the values ... ?!
Okay, gave up ...
If someone would still have an answer, it would be great!
Right now I dont use the OnCheckedChanged-Event of the CheckBoxes anymore.
I just let them select a CheckBox and on the OnClick of the ButtonOk I loop through the CheckBoxes and check which one is selected.
I created a few radiobuttonlist controls on my project, they're created every time the page is loaded, i want to get the value of the radiobutton that the user has selected, but since my radiobuttons were created dynamically, i don't know how to acces to their values nor how to create their event handlers. Is there a way to assign a name or id to the control when i create it?
i hope you can help me.
I create a seires of radiobuttlist on the page_load event, with the text and their values been pulled out of a database. now, the user has to choose one of the options from that radiobuttlist and i want to get the value of the radiobutton the user checked. how do i do that if i don't know the name nor the id of the radiobuttlist since they're created dynamically.
this is what i've got:
for (int i = 3; i < numfields; i++) {
if (dr[i].ToString() != "" && dr[i] != null){
r.Items.Add(new ListItem(dr[i].ToString(), dr[i].ToString()));
//r.SelectedIndexChanged += new EventHandler(rowSelectedIndex);
}
}
so basically i use my datareader to loop through the data in the database, if the value from the field isn't empty or null, then i add an item to the radiobuttlist called "r"
i tried to create an eventhandler for that too, but since i have never worked with them i really don't know what to do. :(
I'm so sorry if i seem way too pathetic.
Taking a quick look at your code:
for (int i = 3; i < numfields; i++) {
if (dr[i].ToString() != "" && dr[i] != null){
r.Items.Add(new ListItem(dr[i].ToString(), dr[i].ToString()));
//r.SelectedIndexChanged += new EventHandler(rowSelectedIndex);
}
}
The most obvious thing that jumps out is your if statement. You should first check for null:
if (dr[i] != null && dr[i].ToString() != ""){
As if dr[i] is null, you'll get an exception (as you'll be trying to call the ToString() method on a null object.
If the contents of dr are always going to be strings, you might consider writing:
if(!String.IsNullOrEmpty(dr[i]){
I also note you start your indexing at 3 - is this because you want to skip the first 3 fields?
Wherever you create your variable, 'r', you can set the name and ID properties. You can use the ID property to look for the control on PostBack. So if you created your radiolist like so:
RadioButtonList r = new RadioButtonList();
r.Id = "MyRadioButtonList";
r.SelectedIndexChanged += MyRadioButton_SelectedIndexChanged;
Which would point at the following event handler:
private void MyRadioButton_SelectedIndexChanged(Object sender, EventArgs e) {
... Do Stuff ...
}
There are several ways of finding your control when you post back; you can look in the Request.Forms collection for a control matching the name of the control you submitted, or, more appropriately, you can use the FindControl method with the ID you gave the control. See C#, FindControl for a post with a method (by Jeff Atwood!) that will search the entire hierarchy of controls for your control.
When you add a dynamic control is important, too. If you add it too late in the page lifecycle then it will not be available on PostBack. See http://support.microsoft.com/kb/317515 for more details on just when to add a control. There are plenty of resources for Dynamic ASP.Net controls around too.
You could put your RadioButton into a list as you create them. This is also when you want to add your handlers.
RadioButton rb;
for (int i = 1; i < 5; i++)
{
rb = new RadioButton();
rb.AutoSize = true;
rb.Location = new System.Drawing.Point(25, (i*25) + 25);
rb.Name = "radioButton" + i.ToString();
rb.Text = "radioButton" + i.ToString();
//Add some event handler?
this.Controls.Add(rb);
lstRadioButton.Add(rb);
}
Whenever you want to know which one is selected you can do a foreach loop of your list and look if your RadioButton is checked.
foreach (RadioButton rButton in lstRadioButton)
{
if (rButton.Checked == true)
{
//Do something
}
}
You are maybe searching for TagName property if the programmatic name isn't enough for you.
The problem is that you are creating the controls in page_load. In order for their values to be posted back into the controls correctly, you must move this creation into the page_init method and recreate them every time.
Then, in page_load, you can access the values in the controls correctly. If you give them IDs using a consistent naming convention, you will be able to find them using the FindControl method or, in page_init, you can store them in a collection at the page or user control level.