Problems with textbox text changed with C# - c#

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.

Related

How to prevent AutoPostBack from resetting my page?

I am building a page that includes some components that are static on the page (dropdowns, buttons, a table to hold them in), but one table cell is filled with variably generated CheckBoxes. When a button is pressed, the code for the page calculates what checkboxes to place and creates a new CheckBox object for each one needed and then adds it to an existing Div on the page.
I am trying to trigger some code to run when any of these are checked or unchecked, but checkBoxName.CheckedChanged += cbCheckedChanged wasn't working. I researched and found two suggestions: enabling viewstate and enabling autopostback.
checkBoxName.EnableViewState = true; seems to make no difference, nor did checkBoxName.ViewStateMode = ViewStateMode.Enabled; or any variations on that i tried. checkBoxName.AutoPostBack = true; did SOMETHING, but it's not allowing it to run the code I want. I think that's because it doesn't reach that point because of the next problem:
With AutoPostBack = true, whenever I check or uncheck a box, cbCheckedChangedis not being executed, and the entire page is reloading, resetting back to it's initial state, therefore removing the checkboxes completely from the table.
How can I fix these problems, or at least where might I start looking?
Edit:
This is where the checkboxes are created:
CheckBox cb = new CheckBox();
cb.Text = CBName;
cb.EnableViewState = true;
cb.ViewStateMode = ViewStateMode.Enabled;
cb.AutoPostBack = true;
cb.CheckedChanged += CBCheckedChanged;
and this is where CBCheckedChanged is:
private void CBCheckedChanged(object sender, EventArgs e)
{
\\Stuff
}
When I use breakpoints to step through it, it never reaches CBCheckedChanged. I have tried every possible combination of commenting out and leaving in the AutoPostBack, ViewStateMode, and EnableViewState lines.
Page_Load is currently empty, nothing runs until the user hits a button.
ViewState is by default enabled for server side controls. You don't have to tinker around with ViewState to solve your problem. ViewState is basically used to restore the state of a control after a postback happens. For example readding all entries to a ListBox control. This is why most control population code is within such a construct in the Page_Load method.
private void Page_Load()
{
if (!Page.IsPostBack)
{
// populate controls here
}
}
ViewState is a very misunderstood concept. There is a great article here that goes into it in detail. But as I said, for your problem ViewState is not a concern.
To solve your problem:
The problem in your case is that the triggered button is creating the CheckBox controls, but when the page is reloaded, because of the CheckedChanged event of these controls, the next page life cycle has no clue of the CheckBox controls that were placed on the page in the previous page life cycle. Dynamic controls need to be generated for every page life cycle!
So what I would do is create a method that:
creates the CheckBox controls and
sets AutoPostback = true for them and
sets the event handler for CheckedChanged
Let's call this method AddDynamicCheckBoxes(). Now you need to call this method in the Page_Load event of your Page when the button was already pressed and also in the event handler of the button's click event. You could do this like follows:
private void Page_Load()
{
if (ViewState["button_was_clicked"] != null)
{
AddDynamicCheckBoxes();
}
}
private void Button_OnClick()
{
AddDynamicCheckBoxes();
ViewState["button_was_clicked"] = true;
}

how to programmatically add more than one item in a webForm asp.net

I try to programmatically add item (like label, table, ...) in my webForm. I tried to create an event click on a button, to add labels each clicks. But every time, it stops to one label, and then nothing happens for the next clicks.
Here's my code for those who want to see what I tried :
protected void btn_Valid_Click(object sender, EventArgs e)
{
this.Page.Form.Controls.Add(new Label() { Text = "test" });
}
Can we do this in asp.net or should I use another language (like javascript) ?
It only creates one Label because that one Label is lost during PostBack.
In your click-event, you have to increase a counter for labels (and/or other controls), and recreate those in Page_Init. EACH and EVERY time the Page posts back. Memorize that counter in the ViewState.
And as usual, I recommend this article about the ASP.NET Page Life Cycle
For those who want a real anwser to this follow this step, it works for me :
Make creation (and not instanciation) in the Page_Init or Page_Load, because for each events those methods are called,
For the example above, don't do kind of this.Page.Forms.Controls.Add(lbl_test), try to find another way like storing the data of those label (in a String Array for example). Here's the code example :
protected void btn_test_Click(object sender, EventArgs e) {
tabLabel[count_tabLabel] = "hello world";
// Do the if(IsCallBack) {} for avoid having your first label skipped
count_tabLabel++;
}
In the Page_Load() function (basically written in the .cs) or by creating the function bellow, do a loop to add those labels to your webForm like this :
protected void Page_Init(object sender, EventArgs e) {
for (int i = 0; i < cpt_l; i++)
{
Page.Form.Controls.Add(tabLabel[count_tabLabel]);
}
}
In fact the page is automatically reloaded, that is the asp page cycle life. So you need at each modifications on your webForm to reload all your items like labels, or more complexes things.
Hope it helps !
P.S.:

Programmatically created controls and their protection level

I am creating a button in the code behind of my aspx.cs page. However I need to detect within this textbox when any text is changed within it after it has been created.
TextBox addn = new TextBox
{
ID = "Tb_Address" + i,
CssClass = "TextBoxProfile",
OnTextChanged = "textChangedEventHandler",
Text = "testc"
};
Tb_Container.Controls.Add(addn);
However OnTextChanged gives me this error:
'System.Web.UI.WebControls.TextBox.OnTextChanged(System.EventArgs)' is inaccessible due to its protection level
I have read around these issues; but I don't have a designer page to change the protection level, neither do I think that would work as these controls are created programmatically.
Edit:
I had tried:
addn.OnTextChanged += textChangedEventHandler;
However this still gives me the above error.
addn.TextChanged += textChangedEventHandler;
The above works, but it's not the desired output, as I wish for this to be automatic and not on PageLoad(?).
OnTextChanged is a method, not an event, you can't subscribe to this, it is the method that raises the event. It is protected so that if you derive from the Textbox class, you can override with your own behaviour. See OnTextChanged method.
TextChanged is the actual event itself that you need to subscribe to, you had done this correctly, but I think you expected it to behave differently? How did you expect it to behave? Netnetter might be on the right lines of using javascript. See TextChanged event.
addn.TextChanged += textChangedEventHandler;
The above works, but it's not the desired output, as I wish for this to be automatic and not on PageLoad(?).
You are subscribing to the text-changed event in way you do it in the ascx file. Since you creating the controls programmatically, you should subscribe to the event like this:
TextBox addn = new TextBox {
ID = "Tb_Address" + i,
CssClass = "TextBoxProfile",
Text = "testc"
};
addn.OnTextChanged += textChangedEventHandler;
Tb_Container.Controls.Add(addn);
you can directly attach event as shown below and take an event handler... and take a look at this answer Dynamically create an ImageButton :-
TextBox addn = new TextBox ;
addn.TextChanged += new EventHandler(b_textChanged);
and its handler :-
void b_textChanged(object sender, EventArgs e)
{
////Your code
}
addn.TextChanged += textChangedEventHandler;
The above works, but it's not the desired output, as I wish for this to be automatic and not on PageLoad(?).
Do you mean that the text change should be detected as you are typing in the values?
because if you mean that then JavaScript is what you need.

How to reference dynamically created controls?

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);

Dynamic Naming of C# Form Elements

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.

Categories

Resources