I am creating a textbox and a checkbox at runtime:
TextBox tb = new TextBox();
tb.Name = "txtPassword";
tb.PasswordChar = '*';
CheckBox cb = new CheckBox();
cb.Text = "Show Password";
cb.Name = "cbShowPassword";
cb.CheckedChanged += new EventHandler(cbShowPassword_CheckedChanged);
And I want to mask or unmask the password according to the checkbox:
private void cbShowPassword_CheckedChanged(object sender, EventArgs e)
{
txtPassword.PasswordChar = cbShowPassword.Checked ? '\0' : '*';
}
The problem is, it doesn't recognize txtPassword and cbShowPassword under cbShowPassword_CheckedChanged, since it is created in the code.
How can I make it work?
As it stands, you use a local variable tb in the method in which you instantiate the control. You can use that variable only in the method that instantiates the control. The fact that you gave the control a name does not mean that there is a variable defined named txtPassword.
You could continue this way, and dynamically look the control up from any other methods that wish to refer to it. However, that makes life harder than it needs to be. What you really want is a variable that refers to the control.
So, create a private member field of your class named txtPassword. Create the control like this:
txtPassword = new TextBox();
txtPassword.PasswordChar = '*';
....
To be really clear, txtPassword is a private member of your class, not a local variable.
Then you will be able to refer to it from other methods. Is there is a possibility that it might not have been created, test txtPassword against null.
Obviously you use the same technique for any other dynamically created controls.
I think you are mixing something up.
Did you add the controls to the parent form/controls?
Does the event fire ? (put a break point in there)
Try to use them as members instead of the name property and access this.cb and this.tb
You could use your form to find any Child controls that matches your newly created textboxes and Checkboxes.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controls(v=vs.110).aspx
Else you could set a reference to this objects in a property on the Form.
Related
Has C# indexed control arrays or not? I would like to put a "button array" for example with 5 buttons which use just one event handler which handles the index of all this 5 controls (like VB6 does). Else I have to write for each of these 5 buttons one extra event handler. And if I have 100 buttons, I need 100 event handlers? I mean something like that:
TextBox1[i].Text="Example";
It could make coding definitely easier for me to work with control arrays. Now I have seen, that C# at least has no visible array functionality on user controls and no "index" property on the user controls. So I guess C# has no control arrays, or I must each element call by known name.
Instead of giving 100 TextBoxes in a for loop 100 incrementing values, I have to write:
TextBox1.Text = Value1;
TextBox2.Text = Value2;
...
...
TextBox100.Text = Value100;
A lot of more work + all these 100 event handlers each for one additional TextBox extra.
I know I'm a little late to this party, but this solution will work:
Make a global array:
TextBox[] myTextBox;
Then in your object's constructor, after the call to
InitializeComponent();
initialize your array:
myTextBox = new TextBox[] {TextBox1, TextBox2, ... };
Now you can iterate your array of controls:
for(int i = 0; i < myTextBox.Length; i++)
myTextBox[i].Text = "OMG IT WORKS!!!";
I hope this helps!
Pete
As I mentioned in comment to a solution by HatSoft, C# Winforms does not allow you to create control arrays like old VB6 allowed us. The nearest I think we can get to is what HatSoft and Bert Evans in their posts have shown.
One thing that I hope would satisfy your requirement is the event handler, you get a common event handler and in the event handler when you typecast the "sender" you get the control directly just like you would in VB6
C#
TextBox textBox = sender as TextBox;
VB6
TextBox textBox = TextBox1[i];
So the only trouble you might have is wiring those 100 TextBoxes to a single event handler, if you are not creating the controls dynamically through code rather creating it manually at design time then all one can suggest is group them in a container like say Panel. Then on Form Load wire them all up to a single event handler like this:
foreach (Control control in myTextBoxPanel.Controls)
{
if(control is TextBox)
control.TextChanged += new EventHandler(control_TextChanged);
}
Just create one handler and point all the buttons to it.
var ButtonHandler = (sender, args) => {
var clicked = (Button)sender;
if (clicked.Text == "whatever")
//do stuff
else
//do other stuff
};
button1.Click += ButtonHandler;
button2.Click += ButtonHandler;
Alternatively, if you are creating controls in code, you could use one of the techniques specified in this answer.
Instead of giving 100 TextBoxes in a for loop 100 incrementing values, I have to write:
for(int i = 0; i <100; i++)
{
TextBox t = new TextBox(){ Id = "txt_" + i, Value = "txt_" + i};
t.TextChanged += new System.EventHandler(this.textBox_Textchanged);
Page.Controls.Add(t);
}
//and for event on TextChanged
private void textBox_Textchanged(object sender, EventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null)
{
////
}
}
Another thing to note: if you really need to edit 100 strings on one form, you should probably think about whether 100 text boxes is really the best way to do it. Perhaps a ListView, DataGridView, or PropertyGrid would be better suited.
This applies almost any time you think you need a huge array of controls.
If you are working with Web Forms and not MVC, you can acces a collection of controls on the page as shown in Using the Controls Collection in an ASP.NET Web Page. Essentially the controls collection is a tree with the page hosting the first level of child controls and some items having children of their own. See How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection for an example of how to follow the tree.
Also, see How to: Add Controls to an ASP.NET Web Page Programmatically.
You can use the same event handler for multiple items as long as the signature required is the same.
For Windows Forms this is nearly identical since they're based on similar architectural models, but you'll want Control.Controls Property and How to: Add Controls to Windows Forms.
Keeping it simple:
TextBox[] keybox = new TextBox[16]; //create an array
for (int i=0; i<16; i++)
{
keybox[i] = new TextBox(); //initialize (create storage for elements)
keybox[i].Tag = i; //Tag prop = index (not available at design time)
keybox[i].KeyDown += keybox_down; //define event handler for array
}
private void keybox_down(object sender, KeyEventArgs e)
{
int index = (int)((TextBox)sender).Tag //get index of element that fired event
...
}
I have a C# Form that prints multiple instances of a User Control. Let's say that the form prints 5 instances of the User Control (Please see the link attached). How can I store/save the data inputted in all User Controls? Thanks
Here is the screenshot of the C# Form:
You'll have to store the User Controls when you instantiate them in a List or something.
You could have a class like this:
class SomeUC : UserControl
{
public SomeUC()
{
}
// A public method.
public string GetData()
{
return textBox1.Text;
}
}
Where textBox1 is the Name of a TextBox in your SomeUC
And then inside your main or something.
// Instantiate a List that will hold your UserControls, this has to be outside all methods
List<SomeUC> list = new List<SomeUC>();
// And now when you want to build your UCs
// Instantiate your UserControl
SomeUC uc1 = new SomeUC();
// Store your UserControl in a List or something (Can't help you with that)
list.Add(uc1);
Add as much as you want.
A List is not the only way you can do that, but since you don't know how many UserControls you're going to build beforehand, it makes since to use a List.
And then you can access them from the list by their index.
SomeUC uc1 = list[0];
string data = uc1.GetData();
This is an example of accessing one control (the TextBox) in your SomeUC. For other classes (such as the ComboBox) the interaction is different. Meaning you won't have a Text property in the ComboBox. You'll have to figure out things like that on youself. A little research is what it takes. You can always come back if you couldn't find a solution for something.
You can create a property like this for each item in user control.
public string DG
{
get
{
return txtDG.Text;
}
set
{
txtDG.Text = value;
}
}
Then you can access the control value by using following line in your form.
supposed you have created a usercontrol MyControl and you have placed some object of this control in FlowLayoutPenal (pnlFLP).
To get value from control
string DG = ((MyControl)pnlFLP.Controls[0]).DG;
To set value in control
((MyControl)pnlFLP.Controls[0]).DG = "1";
Try this code for accessing user control in the page
Dim txtName As TextBox = TryCast(UserControlName.FindControl("txtName"), TextBox)
I have created a textBox control on run-time for my winform application. The control appears just find once the form loads up, and works great too. However, I have just run into a problem as I realize I do not know how to write the code to write to a dynamically created control.
Let's assume I have created a button (named "Button1") on design time. In Button1's click event, (Button1_Click), I would like to write the word "Hello" to a textBox control that won't be created until the application is executed. Some code below:
C# Code:
// Create the textBox control
TextBox new_textBox = null;
int x = 10;
int y = 10;
int xWidth = 300;
int yHeight = 200;
new_textBox = new TextBox();
new_textBox.Text = controlText;
new_textBox.Name = "textBox" + controlName;
new_textBox.Size = new System.Drawing.Size(xWidth - 10, yHeight - 10);
new_textBox.Location = new Point(x, y);
new_textBox.BringToFront();
new_textBox.Multiline = true;
new_textBox.BorderStyle = BorderStyle.None;
// Add the textBox control to the form
this.Controls.Add(new_textBox);
The Problem:
From Button1_Click event, I cannot get in contact with a control that has not even been created yet. Thus, Visual Studio will throw an obvious error that the control does not exist (because it doesn't).
So, is there some way to dynamically call a control, and more
specifically, a textBox control?
Thank you for any help on the matter,
Evan
Declare the new_textBox at class scope. Then the compiler can access it. For example:
class MyForm
{
TextBox new_textBox;
void InitializeTextBox()
{
new_textBox = new TextBox();
// initialization code here
// Add it to the form
this.Controls.Add(new_textBox);
}
void Button1_Click(...)
{
new_textBox.Text = "clicked";
}
You can make the new_textBox a class member (member of the form). You can again assign it a value and add to the forms controls later dynamically.
It would be a good practice to check if is null in the buttonClick event, though.
i have the name of a control in a string and I want to manipulate the control, how do i turn the string into the current form instance of that control in c#?
e.g.
string controlName = "Button1";
What goes here?
button1.text = "Changed";
Thanks
Button button1 = (Button)this.Controls[controlName];
You need to look up the control in the controls collections, then cast it to the correct type. Is this in WPF , WinForms or ASP.Net?
Inside the form, you could write (c#)
this.Controls["Button1"].Text = "Changed";
I suppose, this could be the syntax in vb.net
Me.Controls("Button1").Text = "Changed"
EDIT: I don't know, if that would compile. #Binary Worrier is right
Button btn1 = this.Controls["Button1"] as Button;
btn1.Text = "Changed";
In the code behind of my page I want to attach a label in multiple places. To achieve this and avoid creating mutliple instances of the same label I've tried:
Label lblNone = new Label();
lblNone.Text = "<br/> None. <br/>";
Master.mainContent.Controls.Add(lblNone);
Master.mainContent.Controls.Add(lblNone);
Master.mainContent.Controls.Add(lblNone);
For some reason I only see 1 instance of the "None." on my page?
Why is this?
You have no option.. you need to create one instance of Label for each control you want to see in the screen.
This is because of the behavior of the ControlCollection class.
it will not allow multiple adds of the same "reference".
When you add a control to one ControlCollection it is automatically removed from the previous so, even if you were adding your label to different ControlCollections it wouldn't work.
PS: By ControlCollection I mean the type of the property Master.mainContent.Controls
You might find it easier to create a method for this as so: -
protected void Page_Load(object sender, EventArgs e)
{
this.Controls.Add(CreateLiteral("text"));
this.Controls.Add(CreateLiteral("text"));
this.Controls.Add(CreateLiteral("text"));
}
private Literal CreateLiteral(string Content)
{
Literal L = new Literal();
L.Text = Content;
return L;
}
Thanks,
Phil.