Retrieve TextBox By Name - c#

In my project i know the names of TextBoxes which are dynamically generated is there any solution to retrieve this TextBox text from other methods.In other sense i want to get TextBox by name and want to use in other part of code.
I have TextBox allocated like this...
private void Met(string rowNo)
{
TextBox t2 = new TextBox();
t2.Name = "itemAmt" + rowNo;
PurchaseItemEntryDyPanel.Controls.Add(t2);
}
Is there any way other than using name? Any Solution?

I personaly use name when I want to read posted data from a form.
And I would use Id when controls are supposed to be unique. So the code is a little different:
var t2 = new TextBox();
t2.ID = "itemAmt" + rowNo;
//since you mention in the comments, add it to the panel
yourPanel.Controls.Add(t2);
Then to get the textBox value
var controlId = "itemAmt" + rowNo;
var t2 = ((TextBox)(yourPanel.FindControl(controlId)));
if(t2 != null)
{
//do someting
//t2.Text = "something";
//t2.Enabled = true;
}
If you are not willing to make that change, go over the solution posted earlier.

You can get your TextBox from Controls collection of Form by it's name like this:
var myTextBox = this.Controls[textBoxName];

You don't show too much of your code, but I assume you're adding it to the collection of controls on your form. Otherwise, the TextBox you create in Met goes out of scope when your method ends, just like any other local variable.
private void Met(string rowNo)
{
TextBox t2 = new TextBox();
t2.Name = "itemAmt" + rowNo;
this.Controls.Add(t2); // need to add the TextBox to your form's controls
}
Then you can use Selman22's solution or, if the control might be added to a GroupBox or Panel, you'll want to search all child controls too:
var myControl = this.Controls.Find("itemAmt4", true);
if (myControl != null)
myControl.Enabled = true;

Use this in your Class:
foreach (Control tempCtrl in this.Controls)
{
// Determine he control is textBox1,
if (tempCtrl.Name == "itemAmt" + rowNo)
{
this.Controls.Remove(tempCtrl);
}
}

Related

How to delete (remove) space between textboxes after remove some controls?

I'm new working with C# and I'm asking on here because I didn't find a solution searching in google and other questions on SO, I will explain what my example application does:
When I run it it display a form with a textbox by default, this textbox always will be shown, after type some text and press enter it will generate a new textbox and a new button (all the controls even the default textbox are inside a panel), and the new textboxes have the same functionality as the default textbox, when I click on the button generated next to its textbox it removes the button itself and the textbox but after that if I remove some random textboxes it leaves a space between these controls, how can reorganize this content to dont let space between them?
As you can see in the image, can you tell me how can fix this or give me an advice to achieve this? thank you, by the way this is the method I use to generate the buttons and textboxes
private void GenerarTextBox()
{
panelContenedor.VerticalScroll.Value = panelContenedor.VerticalScroll.Minimum;
TextBox tb = new TextBox();
tb.Text = "Prueba " + id;
tb.Name = "txtBox" + id;
tb.KeyDown += new KeyEventHandler(TextBox_Keydown);
Button bt = new Button();
bt.Cursor = Cursors.Hand;
bt.Text = "X";
bt.Name = "btnPrueba" + id;
bt.Click += new EventHandler(ClickBotones);
Point p = new Point(20, 30 * id);
Point pb = new Point(130, 30 * id);
tb.Location = p;
bt.Location = pb;
panelContenedor.Controls.Add(tb);
panelContenedor.Controls.Add(bt);
tb.Focus();
id++;
}
And this to remove the textboxes and the buttons
private void ClickBotones(object sender, EventArgs e)
{
Button bt = sender as Button;
string nombreBoton = bt.Name;
string idBoton = nombreBoton.Substring(9);
string nombreTextBox = "txtBox" + idBoton;
foreach (Control item in panelContenedor.Controls.OfType<Control>())
{
if (item.Name == nombreTextBox)
{
panelContenedor.Controls.Remove(item);
panelContenedor.Controls.Remove(bt);
}
}
}
You could place your dynamic controls on a FlowLayoutPanel. Either directly or grouped together in a Panel or UserControl.
Set the FlowDirection property of the FlowLayoutPanel to TopDown. The FlowLayoutPanel will then arrange your controls automatically. You can also set the WrapContents property to False and AutoScroll to true to make the scroll bar appear.
Alternatively you can use FlowDirection = LeftToRight, place the text box and the button directly on the FlowLayoutPanel and let the child controls wrap (WrapContents = True). In the child controls, a new property FlowBreak appears. It can be set to True for the last control to appear in a row and let the next one wrap independently of the width of the FlowLayoutPanel.
You can also play with the Margin property of the child controls to control their layout in the FlowLayoutPanel as the Location property becomes useless.
The FlowLayoutPanel (as well as the Panel) is available in the Toolbox in the section "Containers".
When you delete the controls, you need to do a recalc of the positions. So when you have added them in sequence, you can go with:
bool repos = false;
Point p;
foreach (Control item in panelContenedor.Controls.OfType<Control>())
{
if (repos)
{
Point tmp = item.Location;
item.Location = p;
p = tmp;
}
if (item.Name == nombreTextBox)
{
panelContenedor.Controls.Remove(item);
panelContenedor.Controls.Remove(bt);
repos = true;
p = item.Location;
}
}

How to loop through all textBox controls and change associated label color

foreach (Control c in this.Controls)
{
if (c is TextBox && c.Text.Length==0)
{
// [Associatedlabel].ForeColor = System.Drawing.Color.Red;
err = true;
}
instead of [Associatedlabel], I want to associate each textbox to label, so eventually all labels near the textbox that are empty will be red, how it can be done?
Thanks.
There is no fantastic way to find the label control back from the textbox. Using the form's GetChildAtPoint() method is something you can make easily work but are going to regret some day. Naming helps, like FooBarLabel matches FooBarTextBox. Now you can simply use the Controls collection to find the label back:
var label = (Label)this.Controls[box.Name.Replace("TextBox", "Label")];
But Winforms solves many problems by simple inheritance. Add a new class to your project and paste this code:
using System;
using System.Windows.Forms;
class LabeledTextBox : TextBox {
public Label Label { get; set; }
}
Compile and drop the new control from the top of the toolbox. Set the Label property in the designer, just pick it from the dropdown list. Boomshakalaka.
You can first manually set your TextBox's Tag property to these labels. Tag is meant to contain user-defined data, so you can place any object there. Then you can do simply:
foreach (Control c in this.Controls)
{
if (c is TextBox && c.Text.Length==0 && c.Tag is Label)
{
((Label)c.Tag).ForeColor = System.Drawing.Color.Red;
err = true;
}
}
This is the simplest solution, but a few more sophisticated exists though.
Creating a custom composite control consisting of a label, textbox and custom behavior;
Creating a control deriving from a textbox, which stores information about label it is connected with (as Hans Passant suggests)
Creating a Dictionary<TextBox, Label> or Dictionary<Control, Label>, which allows resolving such matters in runtime (variation on Steve's idea).
I suppose that you are using WinForms. In this environment you don't have any built-in functionality that associate a label to a textbox. So you need to build your own association.
This could be done creating a dictionary in the constructor of your code
public class MyForm : Form
{
private Dictionary<string, Label> assoc = new Dictionary<string, Label>();
public MyForm()
{
// Key=Name of the TextBox, Value=Label associated with that textbox
assoc.Add("textbox1", Label1);
assoc.Add("textbox2", Label2);
assoc.Add("textbox3", Label3);
}
}
.....
foreach (TextBox t in this.Controls.OfType<TextBox>())
{
if(t.Text.Length == 0)
{
assoc[t.Name].ForeColor = System.Drawing.Color.Red;
err = true;
}
else
assoc[t.Name].ForeColor = ??? system forecolor ???
}

how to use loops to access form elements in C#?

if(pictureBox1.Tag.ToString() == "accept")
{
char room1 = Convert.ToChar(lbl_roomid1.Text);
row1[13] = (byte)room1;
DateTime sdt1 = DateTime.Parse(txt_sdate1.Text);
//some code
}
if (pictureBox2.Tag.ToString() == "accept")
{
char room2 = Convert.ToChar(lbl_roomid2.Text);
row1[13] = (byte)room2;
DateTime sdt1 = DateTime.Parse(txt_sdate2.Text);
//some code
}
/* What if i wanted to type this code inside a loop?? i need to do the same for 10 pictureboxes */
Something like this:
public void DoMagic(Label label, TextBox textBox)
{
//...
}
And this:
foreach (Control currentControl in this.Controls)
{
if (currentControl is PictureBox)
{
if (((PictureBox)currentControl).Tag.ToString().Equals("accept"))
{
string controlId = currentControl.Name.Remove(0, 11);
string labelName = string.Concat("lbl_roomid", controlId);
string txtName = string.Concat("txt_sdate", controlId);
this.DoMagic(this.Controls.Find(labelName, true)[0] as Label, this.Controls.Find(txtName, true)[0] as TextBox);
}
}
}
Regards
You could make an array of the elements.
The following is a little dirty, but...
class PBRoomDate {
// Helper data holder class. Could probably be an anonymous class in C# 4.0
public PictureBox PB;
public Label RoomLabel;
public TextBox DateText;
PBRoomDate(PictureBox PB, Label RoomLabel, TextBox DateText) {
this.PB = PB; this.RoomLabel = RoomLabel; this.DateText = DateText;
}
}
// [...]
var pbRoomDates = new PBRoomDate[]{
new PBRoomDate(pictureBox1, lbl_roomid1, txt_sdate1),
new PBRoomDate(pictureBox2, lbl_roomid2, txt_sdate2),
new PBRoomDate(pictureBox3, lbl_roomid3, txt_sdate3),
// etc.
};
foreach(var pbRoomDate in pbRoomDates) {
if(pbRoomDate.PB.Tag.ToString() == "accept") {
row1[13] = (byte)Convert.ToChar(pbRoomDate.RoomLabel.Text);
DateTime dt = DateTime.Parse(pbRoomDate.DateText.Text);
}
}
The cleaner solution would be to use a custom UserControl to contain the three elements per "picturebox" and lay those out. That would also be easier to maintain and more extendable should the need arise.
Loops to access form elements in c#.
I usually use something like this.
Let say i have 10 picturebox i name it picturebox1 - picturebox10.
Then
Do a loop for the number to loop to 10 i use a variable no
inside it put this code
String Picturebox = "picturebox" + no.ToString();
Control[] oControl = Controls.Find(Picturebox, true);
foreach(Control foundControl in oControl)
{
PictureBox foundControlA = foundControl as PictureBox;
foundControlA.(methods or property here) = (what you want to put to foundControlA)
}
If you have more controls accompanied by each control you can use the same method. The hint here is that i use the same naming convention on my elements or object in my winforms and loop the variable no according to what you want.

Using dynamically created controls in C#

I am creating an application where a user will input grades and the program will output the weighted average. On load, it will ask for the number of categories for the assignments. The program will then dynamically create textboxes for the user to input information. The problem is that I can not figure out how to read the text that is inputed after I create the textboxes. Here is my code:
TextBox txtbx = new TextBox();
txtbx.Text = "";
txtbx.Name = "txtbx1";
txtbx.Location = new Point(10, 10);
txtbx.Height = 20;
txtbx.Width = 50;
Controls.Add(txtbx);
How can I change this code so I can find the current text in the box when the user submits?
If you are dynamically generating controls then obviously you won't be able to have a field for each one. But if you are trying to access the Controls collection for a named control, the ControlCollection can be indexed by name. After adding the text box with the specified name, you can simply do:
TextBox txtbx = (TextBox)Controls["txtbx1"];
You could use the FindControl method of the Page class.
This method takes a parameter which is the TextBox's ID, which you have to set upon creation:
txtbx.ID = "txtbx1";
Then you can select it:
TextBox txtbx1 = (TextBox)FindControl("txtbx1");
and use it.
Edit: Since the initial question added that he is refering to Windows Forms, my reply above is off-topic.
In Windows Forms, you should simply use a class member variable instead of a local variable. E.g.:
public partial class MyForm
{
...
private TextBox txtbx;
...
private void createControls()
{
txtbx = new TextBox();
txtbx.Text = "";
txtbx.Name = "txtbx1";
txtbx.Location = new Point(10, 10);
txtbx.Height = 20;
txtbx.Width = 50;
Controls.Add(txtbx);
}
private void someOtherFunction()
{
// Do something other with the created text box.
txtbx.Text = "abc";
}
}
This code for the Dynamically Add Textbox On Button Click
int count = 1;
public System.Windows.Forms.TextBox AddNewTextBox()
{
System.Windows.Forms.TextBox txt = new System.Windows.Forms.TextBox();
this.Controls.Add(txt);
txt.Top = count * 25;
txt.Left = 100;
txt.Text = "TextBox " + this.count.ToString();
count = count + 1;
return txt;
}
private void Onbutton_Click(object sender, EventArgs e)
{
//Call the method AddNewTextBox that uses for Dynamically create Textbox
AddNewTextBox();
}
I hope this code will help you .
Thank You
Happy Coding:)
Keep a list of references of all text boxes on the form. Add the textBox reference to the list when you create them dynamically.
Then you can simply iterate through all text boxes in the list when you want to read their text.
Make sure that you name the text boxes as per their related category names. Then you can also Find the control in the list by their names.
class MyForm : Form
{
IList<TextBox> _textBoxes = new List<TextBox>();
private void AddTextBox(string categoryName){
var myTextBox = new TextBox();
myTextBox .Name = categoryName + "txtbx";
// set other properties and add to Form.Controls collection
_textBoxes.Add(myTextBox);
}
private TextBox FindTextBox(string categoryName)
{
return _textBoxes.Where( t => t.Name.StartsWith(categoryName)).FirstOrDefault();
}
}
All you need to do is set up an OnClick listener for your submit button and have it do something like this
private void OnSubmit(object sender, EventArgs args)
{
string yourText = txtbx.Text;
}
You'll have to keep a reference to the text box after you create it. yourText will contain the value you need. Hope this helps

C# dynamically created control issue

i'm having issues retreiving the values out of a dynamically created dropdownlist. all controls are created in the Page_Init section. the listitems are added at that time as well from an array of listitems. (the controls are named the same so should be accessable to the viewstate for appropriate setting.)
here is the function that attempts to retrieve the values:
protected void Eng98AssignmentComplete_Click(object sender, EventArgs e)
{
String myID = "0";
Page page = Page;
Control postbackControlInstance = null;
// handle the Button control postbacks
for (int i = 0; i < page.Request.Form.Keys.Count; i++)
{
postbackControlInstance = page.FindControl(page.Request.Form.Keys[i]);
//Response.Write(page.Request.Form.Keys[i].ToString());
if (postbackControlInstance is System.Web.UI.WebControls.Button)
{
myID = Convert.ToString(
postbackControlInstance.ID.Replace("button_", ""));
}
}
String txtholder = "ctl00$ContentPlaceHolder$Eng098Instructors_" + myID;
Response.Write("MYID: " + myID + "<br/>");
DropDownList ddInstructorCheck = (DropDownList)Page.FindControl(txtholder);
Response.Write("Instructor Selected: "
+ ddInstructorCheck.SelectedValue + "<br/>");
}
here is the output I get, no matter which instructor was selected.....
MYID: 1_1
Instructor Selected: 0
ctl00$ContentPlaceHolder$Eng098Instructors_1_1
the name of the control is correct (verified via view source)....
ideas?
You're going to a lot of work to build this fancy string:
ctl00$ContentPlaceHolder$Eng098Instructors_1_1
That is the client ID of your control, not the server id. This code is running on the server side, and so you need the server id. To get that control using the server id, you need to do this:
ContentPlaceHolder.FindControl("Eng08Instructors_1_1");
Notice I didn't look in the page, because your content place holder created a new naming container.
Also, the way your loop is set up the myID variable will always end up holding the last button in the Keys collection. Why even bother with the loop?
Based on your comments, a better way to find the id of the dropdownlist is like this:
string id = ((Control)sender).ID.Replace("button_", "Eng098Instructors_");
why not just save the control in an instance in your class so that you don't have to use FindControl?
Do you also re-create the controls during the postback? Dynamically generated/added controls must be re-created with every request, they are not automatically re-created.
Why don't you cast the sender? This should be the button that caused the postback:
string myId = "0";
Button btn = sender as Button;
if (btn != null)
myId = btn.ID
...
You need to perform something like this because the UniqueID property is the key in Request.Form.
List<Button> buttons = new List<Button>();
List<DropDownList> dropdowns = new List<DropDownList>();
foreach (Control c in Controls)
{
Button b = (c as Button);
if (b != null)
{
buttons.Add(b);
}
DropDownList d = (c as DropDownList);
if (d != null)
{
dropdowns.Add(d);
}
}
foreach (String key in Request.Form.Keys)
{
foreach (Button b in buttons)
{
if (b.UniqueID == key)
{
String id = b.ID.Replace("button_", "");
String unique_id = "ctl00$ContentPlaceHolder$Eng098Instructors_" + id;
Response.Write("MYID: " + id + "<br/>");
foreach (DropDownList d in dropdowns)
{
if (d.UniqueID == unique_id)
{
Response.Write("Instructor Selected: " + d.SelectedValue + "<br/>");
break;
}
}
}
}
}
I'm not sure why you are generating the control in code (you can still add items dynamically if you do), but the code that generates the controls would probably be a huge help here. I'm guessing you are not setting the list item value, and instead just setting the list item text. Try seeing what you get from the SelectedText field and post your control creation function.
EDIT:
In response to your comment on #Martin's post, you said "yes I recreate the controls in the Page_Init function each time the page is created (initial or postback)". Are you also setting the selected value when you create them?
You can also use controls on the page even if your data comes from a database, the controls themselves don't have to be dynamically generated.
How about this?
((Button)sender).Parent.FindControl(myid)
Edit:I misunderstood your question. But i think you should follow page lifecycle. it is common issue for dynamically created controls.
I did some research and here is some info about Dynamically Created Controls may help you...
I had 2 catches.... here's what they were.
1. I didn't clear the table I was adding to before re-creating the controls.
apparently my attention to detail was off yesterday, i'm pretty sure the ctlXX frontrunner of the control was some different number upon postback due to how I was recreating the controls.
2. I was assigning the same list to all the dropdownlist controls.
once I called the lookup upon each creation a dropdownlist control, all works well.
anyway for what it's worth....

Categories

Resources