Get content of all user controls from a flow layout panel - c#

I have a user control which has a label and a text box. The text box gets the values dynamically at run time. There are n number of dynamic user controls added as shown below:
for loop
{
MyUserControl control = new MyUserControl();
control.SetLabelValue(label);
control.SetTextBoxValue(text);
flowLayoutPanel.Controls.Add(control);
}
flowLayoutPanel is my flow layout panel and SetLabelValue() and SetTextBoxValue() are methods in the user control class to add value to the controls. So lets say in the panel 10 such controls are added. Is there any way i can get the value(text) of all the text boxes which have been added?
Thanks

Use Linq. Substitute c.Text with whatever you use to get at the Value of one of your MyUserControls:
List<String> values = new List<String>();
foreach (MyUserControl c in flowLayoutPanel.Controls.OfType<MyUserControl>())
values.Add(c.Text);

Related

How can ComboBoxes use string resources for item text?

Using C# and WinForms, I can set a form to be localizable, put a label on it, and set text for the label in as many languages as I want. The text will be stored as string resources in one resource file for each language. Then, a user can select a language and all labels on the form will change to the correct language.
This does not seem to work for combo boxes. I can add items to a combo box for a localizable form and they will be stored in resource files using names such as ComboBox1.Item, ComboBox1.Item1, and ComboBox1.Item2, but the displayed text does not change when the combo box changes.
I've seen various suggestions for how to localize combo boxes, based on binding them to dictionaries or lists of tuples, but it seems to me that if items are stored in resource strings, there should be some more automatic way to use those resource strings. Is there?
Edit: Here is what should be a minimal example. A form has a text box, a button, a label and a combo box. The label and combo box each have resources for French (fr-FR) and Spanish (es-ES). The language name is entered in the text box, and the button changes the form's language using the following method:
private void ChangeLanguage(string lang)
{
ComponentResourceManager crm = new ComponentResourceManager(typeof(Form2));
CultureInfo culture = CultureInfo.CreateSpecificCulture(lang);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
foreach (Control c in this.Controls)
{
crm.ApplyResources(c, c.Name, culture);
}
}
The result is that the label's text changes but the text of the combo box items does not.
If you close and reopen the form, everything will work fine. But if you would like to change the culture without closing the form, you need to add extra processing for ComboBox:
if (c is ComboBox)
{
var combo = (ComboBox)c;
var count = combo.Items.Count;
combo.Items.Clear();
combo.BeginUpdate();
for (int i = 0; i < count; i++)
{
var number = i == 0 ? "" : $"{i}";
var item = crm.GetString($"{c.Name}.Items{number}");
combo.Items.Add(item);
}
combo.EndUpdate();
}
crm.ApplyResources(c, c.Name);
Also keep in mind that your function is just applying the resource on the controls on the form and it's ignoring nested controls. For example, if some controls are hosted on a panel, it will ignore them. To fix this issue, take a look at this post.
Note:
In general , I recommend restarting the form to apply new language, because the custom logic is not limited to ComboBox, you need specific logic for ComboBox, ListBox, ListView, TreeView, DataGridView, ToolStrip, ContextMenuStrip, MenuStrip, StatusStrip and maybe smoe other controls which I forget to mention.
In short, I believe saving the selected culture in a setting and then Application.Restart() and applying culture in Main method is what you are looking for.

Duplicate a row on a form

I have a form which initially has one row of boxes for user input. I have a button which, when clicked, should create an identical row below the previous. The button should be able to be clicked more than once, to add multiple rows.
How can I go about implementing this, in a way which gives each control in each row its own unique name (so I can refer to it in my program), and also keeping proper formatting of the rows?
I have tried to set up a class for rows as below:
class SubjectRow
{
//every row has these boxes, plus some more textboxes
public ComboBox subjectBox;
public Label maxBox;
public TextBox aBox;
public SubjectRow(ComboBox _subjectBox, Label _maxBox, TextBox _aBox)
{
subjectBox = _subjectBox;
maxBox = _maxBox;
aBox = _aBox;
}
}
...But I am stumped on how to have the button generate the new controls with their own names. My idea was something like this:
buttonClicked
{
SubjectRow row1 = new SubjectRow(subjectBox1, maxBox1, aBox1);
}
But I need a way to change the control names here without manually typing them all out; there could possibly be a lot of rows on the form.
Is there a way to add more rows to my form using a button, giving each control in each row a unique name? This needs to be done in some kind of loop.

Focus control inside DataGridView control

I have a Form, that contain a DataGridView control named gridParameters.
I'm adding control on-top of it, based on some values, to add controls that are not available (for example, DateTimePicker):
DateTimePicker dtp = new DateTimePicker();
gridParameters.Controls.Add(dtp);
dtp.Location = rowCellLocation;
dtp.Size = rowCellSize;
dtp.CustomFormat = "yyyy/MM/dd";
dtp.Format = DateTimePickerFormat.Custom;
dtp.Tag = rowId;
dtp.ValueChanged += dtp_SelectedValueChanged;
dtp.Visible = true;
That code is inside a loop that iterate throgh the grid rows, and is in an If statement (I add DateTimePicker for some rows and NumericUpDown for others based on a row cell value). The variables rowCellLocation, rowCellSize and rowId are set in a loop for each row.
My DataGridView selection mode is a full row selection.
I want to make the added control (DateTimePicker, NumericUpDown...) get focus when I switch to the row, for example, when I click on a row with the mouse.
To do so, I've tried the following:
In the loop that creates the controls, I set the control to the relevant row Tag property.
In the grid Row_Enter event (I also tried CurrentCellChanged) I added the following code:
if (gridParameters.CurrentRow.Tag != null)
{
((Control)gridParameters.CurrentRow.Tag).Focus();
}
I've also tried using Select() and also
this.ActiveControl = (Control)gridParameters.CurrentRow.Tag;
None of the above sets focus to the control.
I place a break point, and the code is getting to this line, the Tag property contain the control that need to be focused, and execute it, but I can't get the control to focus.
UPDATE: Setting focus to another control outside of the DataGridView, works just fine (for example, setting focus to an "OK" button works).

Is there a textboxlist control available somewhere?

There are ASP controls such as radiobuttonlist and checkboxlist and you can databind them to a database query. It's great for creating dynamic lists with user interaction. What I'm trying to do is generate a list of textboxes in the same fashion. A list of textboxes that behave the same way.
The object is to have a checkboxlist that is generated via datasource/database. When the user is finished selecting items from this list, they click a button. That list hides (using jquery) and a new list is created based on their selections. However, the new list is now a list of their selections accompanied by an empty textbox. The user fills in the textboxes for each entry and submits again which commits it to a database.
SO:
checkbox - description
checkbox - description
checkbox - description
checkbox - description
Becomes:
Description - Textbox
Description - Textbox
The reason that I'm looking for a list-type control is so that I can ultimately loop through it for submission to the database using linq. Does that make sense? My real question is if there is a control like this yet. I gave the full description in case someone has any other ideas, short of creating a custom control.
There's nothing out of the box that does what you describe no. But you can still loop through controls. I would put your form controls inside of an asp:Panel or a div with runat="server" and use something like the following code to cycle through them as you described.
foreach(Control ctl in myPanel.Controls)
{
//check control type and handle
if (ctl is TextBox)
{
//handle the control and its value here
}
}
asp:ListBox has a property named SelectionMode, which can be set to SelectionMode="Multiple" and allows you to select items you want. This is not exactly what you need but it's a simple solution.
After the selection is made in checkboxlist, make a postback to server. Here create a datatable with two columns (description & text). For every selected item in the checkboxlist add a row to this table and bind it to a gridview control. Here 'text' column will be always empty. Configure the gridview to use template column with a textbox in the itemtemplate

How do I extract values from controls and write it on XML?

I have a form which contains infinite number of options which user and add.
Some options are in textbox, and some are in combobox(selected is the value to be extracted).
The form is in a way that user can add as many combo box and text box he wants and let him write those information onto XML.
How do I code that in c#? If anyone can give me a short example of one each which loops through each added combo box and text box, that would be great.
Thank you in advance.
You can iterate through all controls inside a form like this.
foreach(Control control in this.Controls)
{
//here 'this' is representing the form you want to iterate through
//you can check whether it is a combobox or a text box
if(control.GetType() == typeof(Combobox))
{
//this is a combo box
}
else if(control.GetType() == typeof(Textbox))
{
//this is a text box
}
}
using above method you will find the controls inside a particular form. After that you can write information in a XML file

Categories

Resources