I'm having issues adding controls during runtime in winforms c#. It works, but it takes super long time.
I'm trying to add 'Control's containing labels to a TableLayoutPanel (named productTable).
Here is the code:
private void loadTable()
{
List<Product> prodList = controller.getAllProducts();
List<Book> bookList = new List<Book>();
List<Game> gameList = new List<Game>();
List<DVD> dvdList = new List<DVD>();
foreach(Product p in prodList)
{
if (p is Book)
{
bookList.Add((Book)p);
}
else if (p is Game)
{
gameList.Add((Game)p);
}
else if (p is DVD)
{
dvdList.Add((DVD)p);
}
}
if (bookList.Any())
{
int control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in bookList.First().getTitlesList())
{
productTable.Controls.Add(new Label()
{
Text = val,
BackColor = System.Drawing.Color.Silver,
Font = new Font(Label.DefaultFont, FontStyle.Bold)
}, control, productTable.RowCount);
control += 1;
}
foreach(Book book in bookList)
{
control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in book.getValuesAsStringList())
{
productTable.Controls.Add(new Label() { Text = val }, control, productTable.RowCount);
control += 1;
}
}
}
if (gameList.Any())
{
int control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in gameList.First().getTitlesList())
{
productTable.Controls.Add(new Label()
{
Text = val,
BackColor = System.Drawing.Color.Silver,
Font = new Font(Label.DefaultFont, FontStyle.Bold)
}, control, productTable.RowCount);
control += 1;
}
foreach (Game game in gameList)
{
control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in game.getValuesAsStringList())
{
productTable.Controls.Add(new Label() { Text = val }, control, productTable.RowCount);
control += 1;
}
}
}
if (gameList.Any())
{
int control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in dvdList.First().getTitlesList())
{
productTable.Controls.Add(new Label()
{
Text = val,
BackColor = System.Drawing.Color.Silver,
Font = new Font(Label.DefaultFont, FontStyle.Bold)
}, control, productTable.RowCount);
control += 1;
}
foreach (DVD dvd in dvdList)
{
control = 0;
productTable.RowCount = productTable.RowCount + 1;
foreach (string val in dvd.getValuesAsStringList())
{
productTable.Controls.Add(new Label() { Text = val }, control, productTable.RowCount);
control += 1;
}
}
}
}
the 'controller' object in this case just fetches some data-objects (Products). And from the products in this case i only use to return lists of strings (with the metods getTitlesList() and getValuesAsStringList() ).
I run this method (loadTable()) at startup, in the FormMain constructor, and then it works fine and has no delay. But when i try to run the method during runtime with a button_click event, it takes forever (2-3 min). Even if the data has not changed. When I used the debugger it became obvious that its creating the Controls thats taking so much time. Even if i just put empty labels inside it. Actually just running the productTable.Controls.Clear(); takes a strange amount of time (2-3 sec).
Here you can see the problem in action: https://media2.giphy.com/media/ihMH62AYoCKSYuGQlC/giphy.gif
Related
I'm trying to create pricelist for hotel. I'm having a list of dates, and list of room types in hotel. That lists can contain random number of elements. That is created dynamically, and here is the code:
private void CreateControls() { var colIndex = 0;
var vrsteSoba = _Presenter.VrstaSobeDto.ToArray();
foreach (var bindingItem in vrsteSoba)
{
var lbl = new Label()
{
Width = LABEL_WIDTH,
Height = LABEL_HEIGHT - 5,
Left = 10,
Top = 30 + colIndex * (EDIT_BOX_HEIGHT + SPACE_BETWEEN_CONTROL),
Text = bindingItem
};
_dataPanel.Controls.Add(lbl);
colIndex++;
}
int a = 1;
foreach (var date in _Presenter.CeneTarifa)
{
int y = 0;
var panel = new Panel
{
Height = PANEL_HEIGHT * (vrsteSoba.Length-4),
Width = EDIT_BOX_WIDTH,
Left = a * (EDIT_BOX_WIDTH + SPACE_BETWEEN_CONTROL + 50),
Top = 5
};
_dataPanel.Controls.Add(panel);
var label = new Label
{
Height = EDIT_BOX_HEIGHT,
Location = new Point(0, 10),
Text = date.Datum,
Margin = new Padding(0)
};
panel.Controls.Add(label);
int index = 0;
foreach (var item in date.VrstaSobeCena)
{
var box = new TextBox();
panel.Controls.Add(box);
box.Height = EDIT_BOX_HEIGHT;
box.Width = EDIT_BOX_WIDTH;
box.Location = new Point(0, 30 + y * (EDIT_BOX_HEIGHT + SPACE_BETWEEN_CONTROL));
box.DataBindings.Add(new Binding(nameof(box.Text), date, date.Cena[index].Cena1));
y++;
index++;
}
++a;
}
_dataPanel.AutoScroll = true;
}`
Here is image of that representation.
Now I'm facing a problem of data binding. I need to bind price, two way, for each text box. And I'm stuck.
I have tried to bind it to property name, but then all boxes get same value. If I try to bind it to value via index, I'm getting error
Cannot bind to the property or column 34 on the DataSource. Parameter name: dataMember
Code below is used to fill model that is used in presenter
` private void FillCenePoTarifi() { var sobeArr = VrstaSobeDto.ToArray();
foreach (var datum in Datumi)
{
var dictionary = new Dictionary<string, decimal>();
var cene = new List<Cena>();
foreach (var item in sobeArr)
{
var tarif = _Tarife.Where(x => x.SifTarife == item).FirstOrDefault();
if (tarif != null)
_SastavTarife = HotelierServerLocal.Default.TarifaViewBlo.GetSastaveTarife(tarif.IdTarife);
//proveriti ovu logiku
var cena = _SastavTarife.Where(x => x.Cena1 != 0).Select(c => c.Cena1).FirstOrDefault();
cene.Add(new Cena { Cena1 = cena.ToString()});
dictionary.Add(item, cena);
}
var model = new CenePoTarifi
{
Datum = datum,
VrstaSobeCena = dictionary,
Cena = cene
};
CeneTarifa.Add(model);
}
}`
Finally here are classes that use as model.
` public class CenePoTarifi{
public Dictionary<string, decimal> VrstaSobeCena { get; set; } = new Dictionary<string, decimal>();
public string Datum { get; set; }
private List<Cena> _Cena;
public List<Cena> Cena
{
get => _Cena;
set
{
_Cena = value;
NotifyPropertyChanged("Cena");
}
}
public class Cena :
{
private string _Cena1;
public string Cena1
{
get => _Cena1;
set
{
_Cena = value;
NotifyPropertyChanged("Cena1");
}
}
}`
Does anyone has any suggestions?
Your question is: How to bind dynamically created text box. Here is one tested way for accomplishing that specific task.
First create some textboxes dynamically:
public MainForm()
{
InitializeComponent();
buttonRandom.Click += (sender, e) => generateRandomList();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
List<TextBox> tmp = new List<TextBox>();
for (int column = 1; column < tableLayoutPanel.ColumnCount; column++)
{
for (int row = 1; row < tableLayoutPanel.RowCount; row++)
{
TextBox textBox = new TextBox { Anchor = (AnchorStyles)0xF };
tableLayoutPanel.Controls.Add(textBox, column, row);
tmp.Add(textBox);
textBox.KeyDown += onAnyTextBoxKeyDown;
}
}
_textboxes = tmp.ToArray();
// Generate first dataset
generateRandomList();
}
TextBox[] _textboxes = null;
Then, whenever a new random list is generated, clear any old text and databindings from every TextBox before creating a new data binding for it.
public static Random Rando { get; } = new Random(2);
private void generateRandomList()
{
// Clear ALL the data + bindings for ALL the textboxes.
foreach (var textbox in _textboxes)
{
textbox.Clear();
textbox.DataBindings.Clear();
}
// Generate and create new bindings
int count = Rando.Next(1, 79);
for (int i = 0; i < count; i++)
{
var textbox = _textboxes[i];
VrstaSobeCena vrstaSobeCena =
new VrstaSobeCena{ Sobe = (Sobe)tableLayoutPanel.GetRow(textbox) };
textbox.Tag = vrstaSobeCena;
textbox.DataBindings.Add(
new Binding(
nameof(TextBox.Text),
vrstaSobeCena,
nameof(VrstaSobeCena.Cena),
formattingEnabled: true,
dataSourceUpdateMode: DataSourceUpdateMode.OnPropertyChanged,
null,
"F2"
));
// TO DO
// ADD vrstaSobeCena HERE to the Dictionary<string, decimal> VrstaSobeCena
}
}
The classes shown in your code as binding sources may not bind correctly. One issue I noticed is that the property setters are failing to check whether the value has actually changed before firing the notification. Here's an example of doing that correctly. (For testing purposes I'm showing a Minimal Reproducible Sample "mock" version of a class that implements INotifyPropertyChanged.)
enum Sobe { APP4 = 1, APP5, STUDIO, SUP, APP6, STAND, STDNT, COMSTU, LUXSTU, APP4C, APP4L, APP62, APP6L }
class VrstaSobeCena : INotifyPropertyChanged
{
decimal _price = 100 + (50 * (decimal)Rando.NextDouble());
public decimal Cena
{
get => _price;
set
{
if (!Equals(_price, value))
{
_price = value;
OnPropertyChanged();
}
}
}
Sobe _sobe = 0;
public Sobe Sobe
{
get => _sobe;
set
{
if (!Equals(_sobe, value))
{
_sobe = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Finally, one way to test the two-way binding is to intercept the [Enter] key.
private void onAnyTextBoxKeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Enter) && (sender is TextBox textbox))
{
e.SuppressKeyPress = e.Handled = true;
VrstaSobeCena vrstaSobeCena = (VrstaSobeCena)textbox.Tag;
string msg = $"Price for {vrstaSobeCena.Sobe} is {vrstaSobeCena.Cena.ToString("F2")}";
BeginInvoke((MethodInvoker)delegate {MessageBox.Show(msg); });
SelectNextControl(textbox, forward: true, tabStopOnly: true, nested: false, wrap: true);
}
}
Create a List for storing the textbox:
List<TextBox> lstTextbox = new List<TextBox>();
Create a class object that stores the values of "Date" and "room type"
public class RoomTypeDate
{
public string RoomType = "";
public string DateRange = "";
}
Immediately after you created the textbox, assigned the RoomTypeDate info to the tag, add it to lstTextbox.
foreach (var item in date.VrstaSobeCena)
{
var box = new TextBox();
panel.Controls.Add(box);
box.Height = EDIT_BOX_HEIGHT;
box.Width = EDIT_BOX_WIDTH;
box.Location = new Point(0, 30 + y * (EDIT_BOX_HEIGHT + SPACE_BETWEEN_CONTROL));
box.DataBindings.Add(new Binding(nameof(box.Text), date, date.Cena[index].Cena1));
// add the box to the list
lstTextbox.Add(box);
// mark the box with RoomType and DateRange
RoomTypeDate rtd = new RoomTypeDate();
rtd.RoomType = "APP4"; // get the room type
rtd.DateRange = "1.6 - 30.6"; // get date range
box.Tag = rtd;
y++;
index++;
}
Now, to get and set the room price:
public void SetRoomPrice(decimal price, string roomType, string dateRange)
{
foreach (var tb in lstTextBox)
{
var rtd = (RoomTypeDate)tb.Tag;
if(rtd.RoomType == roomType && rtd.DateRange == dateRange)
{
tb.Text = price.ToString();
return;
}
}
}
public decimal GetRoomPrice(string roomType, string dateRange)
{
foreach (var tb in lstTextBox)
{
var rtd = (RoomTypeDate)tb.Tag;
if(rtd.RoomType == roomType && rtd.DateRange == dateRange)
{
return Convert.ToDecimal(rt.Text);
}
}
return 0m;
}
*code untested, might contains bugs
I am trying to create a TextBox based on the selection on ComboBox dynamically based on the following steps:
First step (Select a source from ComboBox):
Second step (Textbox should appear based on ComboBox.SelectedValue):
Last step (A new ComboBox should appear below):
I have created a createTextBox function using the following code:
public void createTextBox(int numPassenger)
{
TextBox[] passengerBoxes = new TextBox[numPassenger];
for (int u = 0; u < passengerBoxes.Count(); u++)
{
passengerBoxes[u] = new TextBox();
}
int i = 0;
foreach (TextBox txt in passengerBoxes)
{
string name = "passenger" + i.ToString();
txt.Name = name;
txt.Text = name;
txt.Location = new Point(244, 32 + (i * 28));
txt.Visible = true;
this.Controls.Add(txt);
i++;
}
}
Is there a way that I can modify my current function to adapt to the mentioned steps? Additionally, how can I find the dynamically created TextBox?
You can try the following code:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
createTextBox(sender as ComboBox);
}
private void createTextBox(ComboBox cmb)
{
TextBox passengerBoxes = new TextBox();
string name = cmb.Text;
if (Controls.Find(name, true).Length == 0)
{
passengerBoxes.Name = name;
passengerBoxes.Text = name;
int textBoxCount = GetTextBoxCount();
passengerBoxes.Location = new Point(244, 32 + (textBoxCount * 28));
passengerBoxes.Visible = true;
this.Controls.Add(passengerBoxes);
if (cmb.Items.Count != 1)//last item remaining then we should not create new combo box
{
ComboBox newCombo = new ComboBox
{
Location = new Point(cmb.Location.X, 32 + ((textBoxCount + 1) * 28))
};
foreach (string str in cmb.Items)
if (cmb.Text != str)
newCombo.Items.Add(str);
newCombo.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
this.Controls.Add(newCombo);
}
}
else
MessageBox.Show("Textbox Already for the selected source " + name);
}
private int GetTextBoxCount()
{
int i = 0;
foreach (Control ctl in this.Controls)
{
if (ctl is TextBox) i++;
}
return i;
}
I have a little problem. First of all, some info:
- On my page, I have an UpdatePanel with a button inside it.
- When you click this button, I generate a new row with dropdown lists. Each time I have to generate a table from scratch, because it resets after the click, so I update [ViewState] value and generate as many rows as clicks.
- Outside the panel, I have another button. After clicking this button, I want to collect data from drop-down lists. To do it, I have to get to these controls.
I tried to use function FindControl(), but I guess I can't - as far as I know, it does not perform a deep search. This means I have to pass as a parameter the exact container with this control. Because control is inside the table, I should get to the <td> value and I can't do that (<td> does not have ID - yes, I can add it but <td> is also dynamically created. That means I would need to get first to <td>, then to my control (guess what - <tr> is also created dynamically).
Because I can't use FindControl function, I use FindRecursiveControl function (code below) The problem is, that this function neither finds anything. Any suggestions about what might be the reason? I added this whole info in case that the reason is for example usage of UpdatePanel and page life cycle.
private Control FindControlRecursive(Control rootControl, string controlID)
{
if (rootControl.ID == controlID)
{
return rootControl;
}
foreach (Control controlToSearch in rootControl.Controls)
{
Control controlToReturn =
FindControlRecursive(controlToSearch, controlID);
if (controlToReturn != null)
{
return controlToReturn;
}
}
return null;
}
My usage of this function:
string control_id = "parametr" + i;
DropDownList dropdown = (DropDownList)FindControlRecursive(UpdatePanel1, control_id);
Script generating table in UpdatePanel after button click
protected void generuj_tabele(int il_klik)
{
il_par.Text = "Ilość parametrów: " + il_klik.ToString();
TableRow table_head = new TableRow();
table_head.Attributes.Add("class", "w3-green");
Table1.Rows.Add(table_head);
for (int j = 0; j < 5; j++)
{
TableCell cell = new TableCell();
table_head.Cells.Add(cell);
}
Table1.Rows[0].Cells[0].Text = "Parametr";
Table1.Rows[0].Cells[1].Text = "Wartość początkowa";
Table1.Rows[0].Cells[2].Text = "Inkrementacja?";
Table1.Rows[0].Cells[3].Text = "Zwiększ o:";
Table1.Rows[0].Cells[4].Text = "Zwiększ co:";
RootObject obj = (RootObject)Session["get_offer"];
for (int i = 0; i < il_klik; i++)
{
parametr = new DropDownList();
wartosc = new TextBox();
inkrementacja = new CheckBox();
inkrementacja_numer = new TextBox();
skok = new TextBox();
//inkrementacja_numer.Enabled = false;
// skok.Enabled = false;
inkrementacja_numer.Attributes.Add("Type", "number");
skok.Attributes.Add("Type", "number");
//inkrementacja.CheckedChanged += new EventHandler((s, eventarg) => checkbox_change(s, eventarg, i));
//inkrementacja.AutoPostBack = true;
//parametr.AutoPostBack = true;
TableRow row = new TableRow();
Table1.Rows.Add(row);
parametr.EnableViewState = true;
wartosc.EnableViewState = true;
inkrementacja.EnableViewState = true;
inkrementacja_numer.EnableViewState = true;
skok.EnableViewState = true;
for (int j = 0; j < 5; j++)
{
TableCell cell = new TableCell();
row.Cells.Add(cell);
}
Table1.Rows[i + 1].Cells[0].Controls.Add(parametr);
Table1.Rows[i + 1].Cells[1].Controls.Add(wartosc);
Table1.Rows[i + 1].Cells[2].Controls.Add(inkrementacja);
Table1.Rows[i + 1].Cells[3].Controls.Add(inkrementacja_numer);
Table1.Rows[i + 1].Cells[4].Controls.Add(skok);
if (i == il_klik - 1)
{
wystaw_liste(obj);
Price pr = obj.sellingMode.price;
parametr.Items.Add(pr.amount.ToString());
List<Parameter> par = obj.parameters;
foreach (Parameter p in par)
{
List<string> val = p.values;
if (val.Count() > 0)
{
foreach (string v in val)
{
parametr.Items.Add(v);
}
}
}
foreach (string p in parametry_list)
{
parametr.Items.Add(p);
}
parametry_list.Clear();
}
parametry.Add(parametr);
wartosci.Add(wartosc);
inkrementacje.Add(inkrementacja);
inkrementacje_numery.Add(inkrementacja_numer);
skoki.Add(skok);
if (i == il_klik - 1)
{
Session["v_parametr"] = parametry;
Session["v_wartosc"] = wartosci;
Session["v_inkrementacja"] = inkrementacje;
Session["v_ink_nr"] = inkrementacje_numery;
Session["v_skok"] = skoki;
}
parametr.ID = "parametr" + i;
wartosc.ID = "wartosc" + i;
inkrementacja.ID = "inkrementacja" + i;
inkrementacja_numer.ID = "inkrementacja_numer" + i;
skok.ID = "skok" + i;
}
}
When I try to check parameters of DropDownList (e.g. SelectedValue) I get error "Object reference not set to an instance of an object"
I have searched a lot for this but really haven't found anything useful yet. So I am asking it here.
I am doing this in Xamarin Android and I have an ItemsGrid class which extends to BaseAdapter. Everything is working fine since I am able to populate the items and show the information I need to show but there is one thing that's not quite right and it is described as follows:
In my GridView I load more items dynamically as I click on a button but the first set of items is added when the activity is created. Everything works fine up to the point where I add more items. Because every time I add more items I set the Adapter to the ItemsGrid new instance (I use new instance every time). That way the items are loaded but the scroll viewer goes up to zero every time. So I added an auto scroll function to automatically scroll into view the first item of the newly created set of items.
The above is my approach currently but I am looking for something more nice and UI friendly as the new Items should be added after the already available items in the view as it happens with "UWP Apps in XAML".
Here is my code for "ItemsGrid.cs":
public class ItemsGrid : BaseAdapter
{
private Context mContext;
private int iCount = 0;
private int mCount = 0;
private string type = "";
private int[] mThumbIds = new int[24];
public override int Count
{
get
{
mThumbIds = getIds();
return mThumbIds.Count();
}
}
public ItemsGrid(Context c, int initialCount, int maxCount, string itemType)
{
mContext = c;
iCount = initialCount;
mCount = maxCount;
type = itemType;
}
private int[] getIds()
{
string[] ids = new string[10000];
for (int b = iCount; b < mCount; b++)
{
ids[b] = b + "";
}
int[] x = new int[mCount];
for (int a = 0; a < mCount; a++)
{
if (ids[a] != null)
{
x[a] = Convert.ToInt32(ids[a]);
}
}
return x;
}
public override Java.Lang.Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return 0;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
RelativeLayout layout = new RelativeLayout(mContext);
ImageView image = new ImageView(mContext);
TextView text = new TextView(mContext);
TextView text2 = new TextView(mContext);
TextView text3 = new TextView(mContext);
if (type == "Movies")
{
Picasso.With(mContext).Load(MoviesActivity.MoviesImageLinks[position]).Into(image);
text.Text = MoviesActivity.MoviesTitles[position];
text2.Text = "Movie";
}
else if (type == "TV Shows")
{
Picasso.With(mContext).Load(TVShowsActivity.TVShowsImageLinks[position]).Into(image);
text.Text = TVShowsActivity.TVShowsTitles[position];
text2.Text = "TV Show";
}
else if (type == "Search")
{
Picasso.With(mContext).Load(SearchActivity.SearchImageLinks[position]).Into(image);
text.Text = SearchActivity.SearchTitles[position];
if (SearchActivity.SearchLinks[position].Contains("movie"))
{
text2.Text = "Movie";
}
else
{
text2.Text = "TV Show";
}
}
image.Id = 2;
//setting text
text.Id = 1;
text2.Id = 3;
text3.Id = 4;
text3.Text = (position + 1) + "";
text.SetSingleLine(true);
text.Ellipsize = Android.Text.TextUtils.TruncateAt.End;
// setting layout
int borderID = HelperClass.GetBorder(mContext);
layout.SetBackgroundResource(borderID);
RelativeLayout.LayoutParams textLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent,
ViewGroup.LayoutParams.WrapContent);
textLayout.AddRule(LayoutRules.CenterHorizontal);
textLayout.AddRule(LayoutRules.AlignParentTop);
RelativeLayout.LayoutParams imageLayout = new RelativeLayout.LayoutParams(180,250);
imageLayout.AddRule(LayoutRules.CenterHorizontal);
imageLayout.AddRule(LayoutRules.Below, text.Id);
RelativeLayout.LayoutParams text2Layout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent,
ViewGroup.LayoutParams.WrapContent);
text2Layout.AddRule(LayoutRules.CenterHorizontal);
text2Layout.AddRule(LayoutRules.Below, image.Id);
RelativeLayout.LayoutParams text3Layout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent,
ViewGroup.LayoutParams.WrapContent);
text3Layout.AddRule(LayoutRules.CenterHorizontal);
text3Layout.AddRule(LayoutRules.Below, text2.Id);
text3Layout.TopMargin = 5;
//adding to layout
layout.AddView(text, textLayout);
layout.AddView(text2, text2Layout);
layout.AddView(image, imageLayout);
layout.AddView(text3, text3Layout);
return layout;
}
}
Scrolling into view:
mGridView.SmoothScrollToPosition(lastListItems - 24);
Getting Items from ItemsGrid class:
mGridView.Adapter = new ItemsGrid(this, lastListItems, numberOfLinks, type);
So if someone has any tips to share about how this can be achieved smoothly, please help me.
Thanks
I want to access multiple textbox name textbox1,textbox2,textbox3, etc.. by loop not by individual name. For that reason I created one function which create this var names.
public string[] nameCre(string cntrlName, int size)
{
string[] t = new string[size];
for (int i = 0; i < size; i++)
{
t[i] = cntrlName.ToString() + (i + 1);
}
return t;
}
for nameCre("Textbox",5); So this,function successfully returning me TextBox1, TextBox2 ... TextBox5.
But when I am trying to convert this string to TextBox control by
string[] t = new string[50];
t= nameCre("TextBox",5);
foreach (string s in t)
{
((TextBox) s).Text = "";
}
it giving me error :
Cannot convert type 'string' to 'System.Windows.Forms.TextBox'....
How can I accomplish this job?
var t = nameCre("TextBox",5);
foreach (var s in t)
{
var textBox = new TextBox {Name = s, Text = ""};
}
string[] t= new string[50];
t= nameCre("TextBox",5);
foreach (string s in t){
TextBox tb = (TextBox)this.Controls.FindControl(s);
tb.Text = "";
}
if you have many text boxes
foreach (Control c in this.Controls)
{
if (c.GetType().ToString() == "System.Windows.Form.Textbox")
{
c.Text = "";
}
}
Perhaps you need this -
string[] t = new string[50];
t = nameCre("TextBox", 5);
foreach (string s in t)
{
if (!string.IsNullOrEmpty(s))
{
Control ctrl = this.Controls.Find(s, true).FirstOrDefault();
if (ctrl != null && ctrl is TextBox)
{
TextBox tb = ctrl as TextBox;
tb.Text = "";
}
}
}
This post is quite old, anyway I think I can give you (or anyone else with a problem like that) an answer:
I think using an Array (or List) of TextBoxs would be the best solution for doing that:
// using an Array:
TextBox[] textBox = new TextBox[5];
textBox[0] = new TextBox() { Location = new Point(), /* etc */};
// or
textBox[0] = TextBox0; // if you already have a TextBox named TextBox0
// loop it:
for (int i = 0; i < textBox.Length; i++)
{
textBox[i].Text = "";
}
// using a List: (you need to reference System.Collections.Generic)
List<TextBox> textBox = new List<TextBox>();
textBox.Add(new TextBox() { Name = "", /* etc */});
// or
textBox.Add(TextBox0); // if you already have a TextBox named TextBox0
// loop it:
for (int i = 0; i < textBox.Count; i++)
{
textBox[i].Text = "";
}
I hope this helps :)