Is there a way to reference dynamically created controls, such as a couple TextBoxes and maybe a RadioButtonList when the user either click a button or changes the selected radio button.
I need to insert a record into a database but I need all of the values. I cannot hard-code the controls because they must be created on the fly.
TextBox t1 = new TextBox();
PlaceHolder1.Controls.Add(t1);
TextBox t2 = new TextBox();
PlaceHolder1.Controls.Add(t2);
RadioButtonList rbList = new RadioButtonList();
rbList.Items.Add(new ListItem("Today", "1"));
rbList.Items.Add(new ListItem("This Week", "2"));
rbList.SelectedIndexChanged += new EventHandler(rbList_SelectedIndexChanged);
PlaceHolder1.Controls.Add(rbList);
I need to reference the two textboxes and the RadioButtonList within rbList_SelectedIndexChanged or some other event. Adding EventHandlers to the textboxes do my no good because I need all three values to insert into the database.
My inital thought was to somehow pass reference of the texboxes to the rbList_SelectedIndexChanged event but I am unsure of how to do this and even more unsure if it will even work.
Any help would be appreciated.
I think you could accomplish this with FindControl(). You'll want to set an ID to those text boxes in the code behinds.
You probably have a reference to PlaceHolder1 within the rbList_SelectedIndexChanged event. So within the event:
var TextBox1 = (TextBox)Placeholder1.FindControl("{text box 1 ID here}");
var TextBox2 = (TextBox)Placeholder1.FindControl("{text box 2 ID here}");
Create a UserControl to encapsulate these controls. Put some logic inside to save both controls depending on their values. Add this user control to the PlaceHolder. View this article for further reading
My inital thought was to somehow pass reference of the texboxes to the bList_SelectedIndexChanged event
That's what I'd do. This is easily done by using an anonymous method for the event handler that can close over the needed variables:
rbList.SelectedIndexChanged += (s, e) =>selectionChangedHandler(rbList t1, t2);
Related
I'm having problems adding an event to an ImageButton. I have to create a set of buttons depending on a selected option from a DropDownList. The buttons are created successfully with Database data, but I'm can't attach the OnClick functionality.
The created buttons must share the same Handler.
protected void cmbServ_SelectedIndexChanged(object sender, EventArgs e) {
ServiceID = cmbServ.SelectedValue.ToString();
ServiceName = cmbServ.SelectedItem.ToString();
DataTable dtFirstTab = new DataTable();
dtFirstTab = mySQLConn.getTable(qryCarry); // LOAD DATA FROM DB
foreach (DataRow row in dtFirstTab.Rows) {
FTabBtn = "btn"+(Convert.ToInt32(row["SKU_Credito"])).ToString();
FTabIconURL = row["SKU_Icon"].ToString();
Panel dvFirstTab = new Panel();
dvFirstTab.CssClass = "col-xs-2";
ImageButton IB = new ImageButton();
IB.ID = FTabBtn;
IB.ImageUrl = FTabIconURL;
IB.Click += new ImageClickEventHandler(btnX_click); // <-- PROBLEM
dvFirstTab.Controls.Add(IB);
pnlIcons.Controls.Add(dvFirstTab); // pnlIcons exists in HTML
}
protected void btnX_click(object sender, ImageClickEventArgs e) {
string Obj = ((ImageButton)sender).ClientID;
Cantidad = Convert.ToInt32(Obj.Substring(3, (Obj.Length) - 3));
txtMonto.Text = "$" + Cantidad.ToString();
}
All the buttons appear correctly, but when I click on them they just fire a "submit" action, acting like there's no OnClick assigned.
No CodeBehid example:
If I add this line in HTML (I removed asp tags)
ImageButton ID="btn10" runat="server" ImageUrl="MontoLogo_10ST.png" OnClick="btnX_click"
It does work as intended.
Any ideas? Thanks a lot!
Creating controls dynamically in ASP.NET webforms usually seems easy at the beginning, but problems are very common when it comes to handling events. Even if you assign your event handler correctly, the event handler is not run in a postback until you re-create all the dynamic controls early in page lifecycle. This explains why the sample with the ImageButton on the ASPX works whereas the dynamically created buttons don't.
See this page for details on creating controls dynamically. The most important part is the warning that basically says: if you need to add dynamic controls, better don't.
Usually you can find a way to create all the necessary controls in markup, for instance using a Repeater control. The big advantage of the repeater is that you have control about the markup that is created.
The following sample outlines the necessary steps:
Place a repeater on your aspx-page. If pnlIcons serves no other purpose than being the container for the dynamically created buttons, substitute it by the repeater. Use the Header- and FooterTemplate properties to add the markup that surrounds the ImageButtons (e.g. the div for dvFirstTab).
Think about which data you need to assign to the image button. In your case, the fields "SKU_Credito" and "SKU_Icon" seem to be required.
Place the Image button in the ItemTemplate of the repeater and bind the properties "Id" and "ImageUrl" to the corresponding fields.
Add a Command event handler and bind the CommandArgument property to a value that helps you discern between the image buttons.
In the command event handler, you can use the CommandArgument to discover which button has been clicked. Add the appropriate code that handles the command.
In the SelectedIndexChanged event handler, read the data from the database and bind the repeater to the result. This creates the rows in the repeater with the ImageButtons.
Ok, I've found the reason. The event handling must be assigned in Page_Load event, so I moved everything inside a method and called it from Page_Load, calling it from "SelectedIndexChanged" doesn't work . It's working now.
Thanks!
I am using C# Wpf and i would like to create a function that once you click on a button A new Textbox will appear is this possible and I want to know if it possible to increase the form hight when a new Textbox is created
The question isnt exactly specific but yes you can make new UI elements in the code-behind. In WPF you would put your button on the window, then add the "Click" event to it. Then in the click event you could code something like. . .
private void Button_Click(object sender, RoutedEventArgs e)
{
Button newButton = new Button(); //Create a new button control and assign it to newButton
newButton.Width = 35; //Access fields like this (You can access any of the ones you access from the Xaml user interface)
newButton.Height = 20;
newButton.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
newButton.VerticalAlignment = System.Windows.VerticalAlignment.Top;
newButton.Content = "click me!";
grMain.Children.Add(newButton); //Add it to the grid
}
grMain is the name of my grid, make sure you name it and call it by the name. You can also call other elements, such as a stack panel or whatever you need. So for your case just make it a textbox instead of a button
Oops didnt see the second part of your question! To resize the window you need to first add a name to it in the XAML (Like you would name a grid or button - just name the window something). And just as we called grMain in my example call that and change the height/width properties.
Add Buttons:
Button button = new Button();
this.Controls.Add(button);
button.Name = "btn" + id;
button.Text = "AAAA";
The result is the name of a button as btn55, but, how to change text on button name btn55?
something like
private void btnaktual_Click(object sender, EventArgs e)
{
btn55.Text = "BBB";
}
Gives me error:
Error 1 The name 'btn55' does not exist in the current context
Use this.Controls.Find("btn55",true).FirstOrDefault().Text = "BBB";
If you used the designer to put the button in the form, then a member variable would be created with the same name as the name of the form. As you create the button using code, there is no btn55 variable.
When you create the button you have a reference to it. You should just keep that reference so that you can use it later. Make a member variable in the form where you can store it, i.e. declare Button button; (or perhaps a more descriptive name) in the form class instead of inside the method where you create the button. Then you can use the variable later to access the button.
Your entire problem lies in the page load. When you click the button event the page posts back, so if you're control is not reloaded it no longer exists when the click event is called. Either you are not creating the button on postback or the button isn't in viewstate. Find Control will always return null until the button is created so most of these answers won't work for you yet.
These pages will help you:
http://forums.asp.net/t/1186195.aspx?FAQ+Why+do+dynamic+controls+disappear+on+postback+and+not+raise+events+
Dynamically Created Controls losing data after postback
http://www.codeproject.com/Articles/35360/ViewState-in-Dynamic-Control
Once you get that control reloaded, then you can get it from there pretty easily.
Try this:
var btn = Controls.Find("btn55") as Button;
btn.Text = BBB;
You need to search for the button in it's parent controller. Let's say you have a main form and the button placed in it. You can find using id of control in parent.
(MainForm.Controls.Find("btn"+number") as Button).Text= "BBB";
I am having a problem with having the eventhandler textchanged method to work with an array of textboxes. The textboxes are generated through C# and not through ASP.NET.
here is the TextBox code in C#:
int i = 1;
foreach(string a in data)
{
i++;
TextBox text = new TextBox();
text.TextChanged += new EventHandler(updateone);
text.AutoPostBack = true;
text.ID = Convert.ToString(i);
}
I tried out the Text.AutoPostBack false and true and I had the same result. The updateone method is not even touched when I change the text of the textbox. When I do change the text
of the textbox it does update the website, but again the updateone method is not even touched in the code. Here is the updateone code:
protected void updateone(object sender, EventArgs e)
{
TextBox text = (TextBox)sender;
}
I thank everyone for their help! I am just confused why this is not working... and also I have to use the C# method and not the ASP.NET way.
have you tried storing references to your TextBoxes in an instance member so that they don't get garbage collected?
something like:
List<TextBox> textBoxes = ...
//in a loop
text.ID = Convert.ToString(i);
textBoxes.Add(text);
-- edit
also, as a rule of thumb, put as much logging in your application as possible.
Whether it is NLog, any other logging tool or even a simple Console.WriteLine(), seeing what your code is actually doing is very helpful.
Since you've confirmed that you're posting your actual code and don't seem to get what I'm trying to say, let me try to explain in an answer.
First problem: Your array of TextBoxes does not exist, which the other answer has already addressed and you've apparently fixed but haven't updated the code in your question to show your fix.
Second problem: The TextBoxes you create are not being added to your form in any way. I'm not sure how you're testing your event handler without doing that.
Third problem: Your event handler updateone doesn't do anything. Imagine you walk into a grocery store, pick up an orange, put it back down, and then leave. That's what your event handler is doing. Instead of just instantiating a temporary TextBox and then doing nothing, try making a message box pop up, or changing the text of another control that exists on the form.
Maybe something like this will work:
List<TextBox> textboxes = new List<TextBox>();
int i=1;
foreach(string a in data) // I assume data is a list or array of strings
{
// I'm not sure why you iterate over data if you don't use it at all inside the loop...
++i;
TextBox text = new TextBox();
text.TextChanged += new EventHandler(updateone);
text.AutoPostBack = true;
text.ID = Convert.ToString(i);
// Add the TextBox to form here, not sure what the call is
}
Label info = new Label;
Label.Text = "Hello!";
// Add Label to form here, again not sure what the call is
And then your event handler:
protected void updateone(object sender, EventArgs e)
{
info.Text = ((TextBox)sender).Text;
}
You are dynamically creating ASP.NET controls. This means that they will not be automatically re-created on the postback of the form. Also, the controls have to be created in the Page_Init event, not the Page_Load event.
So the question is, where and when are you creating the textboxes. Make sure they are created at the Page_Init stage, and you are creating them in the request and in the postback.
My app needs to be able to dynamically create new form elements and work with them. Right now I have a panel with buttons and labels in it. I need to be able to make a duplicate of this and show it in my app and then work with it.
For example, I have panel1. Inside are label1, button1, and button2.
Label 1 just counts up by seconds.
When you click button1, label1 starts counting up. When you click button2, the timer stops.
My problem is that I need to be able to duplicate panel1 many times and still have the new buttons correspond to the correct labels.
On button_click
private void button1_Click(object sender, EventArgs e)
{
Button theSender = (Button)sender;
Panel parentPanel = (Panel)theSender.Parent;
}
From here, I can't target any of the child control . I'm used to targeting and handles in jQuery, so I don't even know the correct C# terminology for how to explain myself.
If understand your problem correctly, I recommend you to make a Usercontrol with a Panel and fill it with your Label, Button and whatever. Write the events for your buttons in the usercontrol. Then introduce this usercontrol in your form and it should work. You can introduce any number of usercontrols in your form and each button will behave/work for the label in that usercontrol only.
As you mentioned you are new in winforms and you are not sure what I am saying, let me know and I will help if I get enough time.
Hope it helps.
Children of a control can be accessed using Control.Contrtols collection, e.g. to access button on a form:
Button btn = this.Controls["button1"];
But that is only true if button1 is placed directly on your form and button1.Name property is set to "button1" (designer does that automattically, if you are creating your controls dynamically, you have to take care of naming your controls yourself.)
You can also enumerate child controls of any control, e.g. child controls of panel1:
foreach(Control c in panel1.Controls)
{
// do something, e.g.
if(c is Label){//do sth...}
if(c.Name.Equals("label1") && c is Label)
{
Label l = c as Label;
}
}
and as #rapsalands said, UserControl may be an answer for you.
I would create a user control (UserControl) for this.
Check this article for more explanation about the difference between Control and UserControl.
Controls and UserControls are easy to duplicate and the full functionality is there.
You can create new UI Controls in code as you would any other object: Button b = new Button();
Then you can add them to the form using form.Controls.Add(b). You'll need to position and size the controls as well (there are properties available for doing this) and hook up your event handlers using b.Clicked += form.button_click;.
To see an example of this, you can try having a look at the designer.cs file that is generated in Visual Studio (don't make changes to it, just have a look). It will look quite complex at first but might go some way to helping demystify Windows Forms, and you will be able to find all of the properties you need to set in there.
Whenever you update something in the designer, Visual Studio generates new code and puts it in the designer.cs file. The entire form is set up in the InitializeComponent() method, which is called from the constructor of your form. You should be able to copy some of that code and with a couple of modifications use it for creating your own dynamic UI elements.
As rapsalands says, it sounds like a user control would be useful in this situation, as it will help encapsulate the functionality you're after. However that may take a bit of time to get your head round and you may find it simpler for now to do everything in your form without creating a new control.
So you are a beginner and need some time to understand Usercontrol as I mentioned in my previous answer. Use a for loop in the Constructor or Load event of your form to dynamically generate controls.
Panel panel;
Label label;
Button button1;
Button button2;
for(int i = 0; i > count; i++)
{
panel = new Panel();
button1 = new Button();
button2 = new Button();
label = new Label();
panel.Controls.Add(button1);
panel.Controls.Add(button2);
panel.Controls.Add(label);
Controls.Add(panel);
button1.Click += Event1;
button2.Click += Event2;
}
private void Event1()
{
label.Text = "Button 1 Clicked."
}
private void Event2()
{
label.Text = "Button 2 Clicked."
}
This way certainly you can create as many controls you want and will also serve your purpose. Use some variables to locate the panel controls appropriately. Set any properties you wish to add in the for loop for the controls.
This is just an alternative for my previous answer. I still recommend the previous answer given by me. This code is dummy and not tested.
Hope it helps.