I have created a textbox programatically in page load as using the below code:
HtmlTableRow row = new HtmlTableRow();
HtmlTableCell cell1 = new HtmlTableCell();
HtmlTableCell cell2 = new HtmlTableCell();
cell1.Controls.Add(new Label() { ID = LableID1, Text = Name });
cell2.Controls.Add(new TextBox() { ID = TextBoxID1 });
row.Cells.Add(cell1);
row.Cells.Add(cell2);
dynamictable.Rows.Add(row);
And In the button click event i am trying to get the value from the Textbox and assign that value to anohter TextBox which is statically created as below:
string id = TextBoxID1
TextBox tb = (TextBox)dynamictable.FindControl(id);
string valuetext = tb.Text;
TextBox1.Text = valuetext;
Am getting Object Reference Error, I mean, i am not able to Find the control and create the TextBox.
I have tried to create the TextBox as below method also:
TextBox tb = (TextBox)form1.FindControl(id);
TextBox tb = (TextBox)this.form1.FindControl(id);
TextBox tb = (TextBox)page.FindControl(id);
Any help would be highly helpful for me.
I think you might need to find the row and then the cell and then find the textbox.
Means inpite of doing this:
TextBox tb = (TextBox)dynamictable.FindControl(id);
You need to find the specific row first like
// find by it or index etc
HtmlTableRow tb = (HtmlTableRow)dynamictable.FindControl(id);
// Then find the Table cell and then find textbox..
I hope this will help you
In order to work with dynamic controls you need to fully understand the ASP.Net Page Life-cycle
Dynamic controls need to be recreated on each post, there's no magic behind responsible of creating your dynamic controls for you, sadly you have to create them explicitly.
Remember that a page is simply a class that is created when you perform a request and destroyed when the response is sent back to the user. Therefore controls need to be recreated every time. This is done for you when the controls are statically declared on the page. But with dynamic controls, you need to recreate them on each post
The code provided by #BobTodd is a good start point, however the recommendation from Microsoft is that dynamic controls should be created in the Page_Init event in order to sync their events with the rest of the static controls.
So your code would look like:
protected void Page_Init(object sender, EventArgs e)
{
CreateTable();
}
Now, remember this simple rule of dumb, when working with dynamic controls, use always the same ID. This is really important because the page viewstate is loaded back based on the control's ID.
Another thing to consider is that all controls created in the Init event, won't load their viewstate until the LoadViewState method is called on every control on the page. This means that if you subscribe to the Page_PreLoad or Page_Load events, you can safely set the control's properties since their value were already loaded from the viewstate and therefore your new values won't be overridden.
This means that any property assigned to the controls before the PreLoad event, will be replaced by the page viewstate value. Therefore is considered a good practice to set your dynamic controls properties after the viewstate has been loaded.
As a quick view, check the ASP.Net page life-cycle:
You might have a method that creates the table, you need to call it on postback to ensure everything is setup.
protected HtmlTable dynamictable;
protected TextBox tb = new TextBox();
protected override void OnInit(EventArgs args)
{
base.OnInit(args);
CreateTableRows();
}
private void CreateTableRows()
{
HtmlTableRow row = new HtmlTableRow();
HtmlTableCell cell1 = new HtmlTableCell();
HtmlTableCell cell2 = new HtmlTableCell();
cell1.Controls.Add(new Label() { ID = LableID1, Text = Name });
cell2.Controls.Add(tb });
row.Cells.Add(cell1);
row.Cells.Add(cell2);
dynamictable.Rows.Add(row);
}
protected void OnClick(object sender, EventArgs args)
{
return tb.Text;
}
use hidden field to store value of dynamically created text box in java script
also add runat="server" in hidden feild
and you can access your textbox value from hidden feild.
Another way is to store that value in query string using javascript and then reading from it at back end
Related
I have dynamically created a button using a function I made which is meant to increase the value of another button created using a similar function. I'm able to retrieve the name of the dynamically created textbox, but since it is dynamically created, I can't reference it.
I've tried to pass the textbox through as a parameter, but it doesn't appear that I'm able to pass extra parameters:
Button ButtonDecreaseValue= addButton(ItemName, "-");
TextBox TextBoxItemAmount = addTextBox(ItemName, "0");
So, how would I change the value of textbox one when ButtonRemoveItem is clicked?
I've created an event handler for the button, like so:
ButtonIncreaseValue.Click += new EventHandler(ItemDecreased);
But, inside the event handler, I'm unsure how I would change the textbox name.
private void ItemDecreased(object sender, EventArgs e)
{
Button currentItem = (Button)sender;
int ItemNo = Convert.ToInt32(currentItem.Tag);
DataRow ItemInfo = getItemDetails(ItemNo);
ItemInfo[0].ToString();
}
When clicking the button, the corresponding textbox should decrease in value.
Assuming this is Windows Forms
You said you have the name of the TextBox? You should be able to find it with that.
private void ItemDecreased(object sender, EventArgs e)
{
string textBoxName = HoweverYouGetTheDynamicTextBoxName();
// Assumptions:
// 1. ItemDecreased is a method on a Form or a UserControl.
// 2. There is only one TextBox with the given name in the Form or UserControl.
// 3. The TextBox is added to the Form or UserControl's Controls property.
TextBox tb = Controls.Find(textBoxName, true).OfType<TextBox>().SingleOrDefault();
if (tb is null)
{
// Couldn't find the text box for some reason.
}
// tb references the dynamically created text box.
}
- Primary Info:
In my recent project, I need to have a page with a DropDownList with some items like 'firstName' , 'lastName' , 'Age' and etc. I want to add optional controls to the page when every item selected by user. For example when user select the 'Age' another dropdownlist created dynamically with these values : 'Less than 10'
'Between 10 and 30'
'more than 30'
Here is a button that add this user selection to listBox and let user to choice another options. (I made a query at last according to user choices and send it to db)
- What I do:
I create a dropDownList and set it's AutoPostBack property to true and adds some items in it and user must select one of those item. then I add user SelectedValue of dropDownList in a Cache variable before page post back happens:
protected void DropDownListColumnNameSelectedIndexChanged(object sender, EventArgs e)
{
Cache["SelectedKey"] = dropDownListColumnName.SelectedValue;
}
When user select an item from dropDownList *DropDownList_SelectedIndexChanged* fire, and I must create controls dynamically in a place holder:
var textBoxName = new TextBox
{
ID = "textBoxName",
CssClass = "str-search-textbox-highlight",
ViewStateMode = ViewStateMode.Disabled
};
placeHolderFirstItem.Controls.Add(textBoxName);
- What is the problem?
When I try add new control in current Button_Click event, control added successfully to page but I can't find it by placeHolderFirstItem.Controls.Find("textBoxName") actually placeHolderFirstItem.Controls.Count is always zero. So I can't get textBoxName.Text values.
I try to google that for any solution and I found some solution that I must add controls in Page.OnInit so I add controls in overridden OnInit(e):
protected override void OnInit(EventArgs e)
{
if (!Page.IsPostBack) return;
var textBoxName = new TextBox
{
ID = "textBoxName",
CssClass = "str-search-textbox-highlight",
ViewStateMode = ViewStateMode.Disabled
};
placeHolderFirstItem.Controls.Add(textBoxName);
}
after doing this I can find "textBoxName" in placeHolderFirstItem, but it fire before DropDownList_SelectedIndexChanged !
so how can I add new controls to place holder exactly when user change the dropDownList value and how can I read new controls value?
Thanks in advance,
Mohsen.
- Updated:
Here is the better solution
(http://forums.asp.net/p/1959726/5596531.aspx?p=True&t=635244790943067485&pagenum=1)
When you are dynamically adding controls, you have to reload the controls into the control tree everytime thereafter for it to appear. With the help of viewstate, you could change your code sample to have:
ViewState("ShowTextbox") = true
And then in your init routine:
protected override void OnInit(EventArgs e)
{
if (!Page.IsPostBack) return;
if (ViewState("ShowTextBox") == true) {
var textBoxName = new TextBox
{
ID = "textBoxName",
CssClass = "str-search-textbox-highlight",
ViewStateMode = ViewStateMode.Disabled
};
placeHolderFirstItem.Controls.Add(textBoxName);
}
}
Please note it's much easier to have a control on the control tree, and then show/hide by setting Visible to true/false, because of these ASP.NET control tree issues.
I have an application where I need to add multiple (and nested) controls to a PlaceHolder. The user enters the number of 'weeks', and my application adds a RadSplitter (using the Telerik control set), along with the relevant panes/grids for the weeks. I add these controls using code behind.
This works fine when first binding (when entering the number of weeks, and clicking Submit). But I also need to enable drag and drop functionality between the controls, which causes a postback.
It seems that the number of controls in my placeholder is always '0' on postback, so I'm guessing they are not being stored in the ViewState. Rather than have to readd these on every postback, how can I ensure my controls are stored in the ViewState?
Here's some example code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (plcSplitter.Controls.Count > 0)
plcSplitter.Controls.Remove(plcSplitter.Controls[0]);
var splitter = new Telerik.Web.UI.RadSplitter();
splitter.Width = Unit.Percentage(100);
int noOfWeeks = int.Parse(txtNoOfWeeks.Text);
DateTime dt = new DateTime(2012, 05, 13);
for (int i = 0; i < noOfWeeks; i++)
{
var range = new Common.DateRange(dt.AddDays(-6),dt);
var pane = new Telerik.Web.UI.RadPane();
Label lbl = new Label();
lbl.ID = "lblText";
lbl.Text = range.To.ToShortDateString();
pane.Controls.Add(lbl);
var gv = AddGrid(i);
pane.Controls.Add(gv);
splitter.Items.Add(pane);
var splitLine = new Telerik.Web.UI.RadSplitBar();
splitter.Items.Add(splitLine);
dt = dt.AddDays(-7);
}
plcSplitter.Controls.Add(splitter);
splitter.DataBind();
}
Controls are not stored in the viewstate, only some of control properties can be stored in viewstate. So, on postback you must create these labels again.
Move that logic to create labels from btnSubmit_Click to separate method, call that method on button click and store data needed to recreate labels somewhere (maybe session), then on postback in OnInit method check for that stored data and if there is some labels create it at that event.
Be sure to read this blog post about viewstate :
http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
and this about creating controls in runtime
http://weblogs.asp.net/infinitiesloop/archive/2006/08/25/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_.aspx
You can store the data necessary to build your controls in the ViewState, but the really important part is that you make sure your controls are built before you try to access them.
Here's a super basic example.
protected void Page_Load(object sender, EventArgs e)
{
BuildControl(GetLabelData());
}
private Tuple<string, string> GetLabelData()
{
if (Page.IsPostBack)
return (Tuple<string, string>)ViewState["MyLabelData"];
else
return new Tuple<string, string>("lblTest", "Test");
}
private void BuildControl(Tuple<string, string> t)
{
Label l = new Label();
l.ID = t.Item1;
l.Text = t.Item2;
ViewState["MyLabelData"] = t;
plcSplitter.Controls.Add(l);
}
protected void bDoSomething_Click(object sender, EventArgs e)
{
Response.Write(String.Format("plcSplitter.Controls.Count:{0}", plcSplitter.Controls.Count));
}
It's also very important to recognize that these controls are being built at the server and if they can be altered by the client you'll need to implement some mechanism of communication for the important bits of info so you can rebuild your controls and then apply any modifications from the client.
For example you are implementing a draggable control, on the client side when you drag you'll need to store the coordinates in a hidden control manually so that can be posted back to the server and you can have that info available when you're rebuilding the controls.
I think the reason those controls are not stored in the ViewState is that they are being added to the page "too late", after the page ViewState is generated. Look at this post:
Last event in page that can still affect a page's viewstate
I have a GridView with a item template defined like:
public class ToolLogTemplate : ITemplate
{
public String DataField { get; set; }
public ToolLogTemplate(String column)
{
DataField = column;
}
public void InstantiateIn(Control container)
{
var textBox = new TextBox();
textBox.ClientIDMode = ClientIDMode.Predictable;
textBox.CssClass = "ToolLog";
textBox.AutoPostBack = true;
textBox.DataBinding += textBox_DataBinding;
container.Controls.Add(textBox);
}
void textBox_DataBinding(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
var context = DataBinder.GetDataItem(textBox.NamingContainer);
textBox.Text = DataBinder.Eval(context, DataField).ToString();
}
}
The GridView is inside of a UpdatePanel defined like:
UpdatePanel updatePanel = new UpdatePanel();
updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;
The TextChanged event of the TextBoxes in the GridView trigger a full refresh of the page. My understanding was that by wrapping the TextBoxes in a UpdatePanel it would trigger a partial refresh instead. Am I misunderstanding this?
Update in response to the newest comment on the question:
I have some javascript attached to the textboxes:
currentTextBox.Attributes.Add("onFocus", String.Format("document.getElementById('RowTextBox').value = {0}; document.getElementById('ColTextBox').value = {1}; this.style.backgroundColor='#ffeb9c';", i, j));
currentTextBox.Attributes.Add("onBlur", "this.style.backgroundColor='#ffffff'");
It just sets the colors of the textbox and saves where it is in the gridview. The updatepanel works as expected with the menu and button I have in it, it's just the textboxes that cause a full postback.
Upon seeing update code, I have revised my answer...
The UpdatePanel needs to be told which controls it should respond to. You can do this by adding Triggers. In your case, you have TextBox controls within a GridView. These Textboxes are set to autopostback. Since they are within the GridView, I believe the GridView is treating them like a RowCommand. Using your original code, I would recommend you add the following:
UpdatePanel updatePanel = new UpdatePanel();
updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;
gridView.OnRowCommand = "GridViewRowCommand";
AsyncPostbackTrigger newTrigger = new AsyncPostbackTrigger();
newTrigger.ControlID = gridView.ControlID;
updatePanel.Triggers.Add(newTrigger);
Within your codebehind, you would need to do something like this:
protected void GridViewRowCommand(object sender, RowCommandEventArgs e)
{
var myTextBox = e.Row.FindControl("myTextBoxID");
// Do some work
}
Well unfortunately I was never able to make the model described here work. Instead I put an invisible button inside of the updatepanel and had javascript click it on the textboxes onchange event. I don't know why this method works and the TextChanged one doesn't, but that's how it ended up going down.
I am adding some checkboxes dynamically during runtime, and I need to know whether they are checked or not when I reload them next time.
I load the checkbox values from a list stored in ViewState.
The question is: when do I save or check for the value of the the Checked?
I tried the event dispose for the check box and the place holder I am adding the checkboxes in, but it wasn't fired. i.e. when I put a break point it didn't stop. So any suggestions?
This is a sample code, but I don't think it is necessary:
void LoadKeywords()
{
bool add = true;
foreach (string s in (ViewState["keywords"] as List<string>))
if (s == ddlKeywords.SelectedItem.Text)
{
add = false;
continue;
}
if (add)
(ViewState["keywords"] as List<string>).Add(ddlKeywords.SelectedItem.Text);
foreach (string s in (ViewState["keywords"] as List<string>))
{
CheckBox kw = new CheckBox();
kw.Disposed += new EventHandler(kw_Disposed);
kw.Text = s;
PlaceHolderKeywords.Controls.Add(kw);
}
}
If you are dynamically adding controls at run time you have to make sure that those controls are populated to the page's Control collection before ViewState is loaded. This is so that the state of each checkbox can be rehydrated from Viewstate. The Page Load event, for example, is too late.
Typically you would dynamically add your CheckBox controls during the Init Event (before view state is loaded) and then Read the values in your Checkbox controls during the Load event (after view state is loaded).
eg:
protected override void OnInit(EventArgs e)
{
//load the controls before ViewState is loaded
base.OnInit(e);
for (int i = 0; i < 3; i++)
{
CheckBox cb = new CheckBox();
cb = new CheckBox();
cb.ID = "KeyWord" + i.ToString();
cb.Text = "Key Word"
MyPlaceHolder.Controls.Add(new CheckBox());
}
}
//this could also be a button click event perhaps?
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (Page.IsPostBack)
{
//read the checkbox values
foreach(CheckBox control in MyPlaceHolder.Controls)
{
bool isChecked = control.Checked;
string keyword = control.Text;
//do something with these two values
}
}
}
Hope that helps
****EDIT****
Forgot to mention that this is obviously just demo code - you would need to flesh it out.
For more information on dynaic control rendering in ASP.Net check out this article on 4Guys.
For more information on the page life-cycle in ASP.Net check out MSDN.
How to:
try adding a javascript code, that handles checked(),
u can get the checkboxes by using document.findElementById(ID) , then store the checkboxe's value into a hiddenfield that has a runat="server" property.
When to:
either on pageload , check if page is postback(), and check the hiddenfield(s) value(S). or add a submit button (and place its event in the code behind, runat="server" property).
hope this helps u.