As you know, I am busy migrating a project from eMbedded Visual Basic to .NET Compact Framework and C#. A key component in the legacy code is the way controls are populated and this is an area where I've had to workaround an issue in .NET Compact Framework.
In eVB you could do this:
Form(sControlName).Text = "Some value"
In other words, you could easily loop through all controls in a form and save names and values.
For iCounter = 0 To Form.Controls.Count - 1
sControlName = Form.Controls(iCounter).Name
You could then retrieve control names and values from the database and re-populate forms. In eVB, all controls in the form sit in the Form.Controls-collection. In .NET Compact Framework you can not address a control by its name in the Form.Controls-collection, only by its index in the collection:
Form.Controls[formControlIndex]
Furthermore, all controls in the form do not sit in the Form.Controls-collection. For instance, if you place controls in a panel, then those controls are found in the Form.Controls[IndexOfPanel],Controls-collection. I've solved these two migration issues by using a hashtable that stores the name of the control as the hash-key, and the control's index as the hash-value. In order to keep track of controls sitting in panels, I add the panel name to the control name when populating the hashtable.
First, when saving the data, I loop through the controls in the form:
foreach (Control formControl in Form.Controls)
{
/// Don't add data from disabled controls!
if (formControl.Enabled)
{
// Pull out control: the control, form and index
// Is control a panel?
if (formControl.GetType().ToString() == "System.Windows.Forms.Panel")
{
// Get index of formControl, ie the panel
formControlIndex = Form.Controls.IndexOf(formControl);
// Loop through controls in panel
foreach (Control panelControl in Form.Controls[formControlIndex].Controls)
{
containerName = formControl.Name;
// Call save method. Pass ID, name of the form, the entire CONTROL that
// sits IN the panel, and the name of the panel.
SaveControl(ID, sFormName, panelControl, containerName);
}
}
else
{
// Call save method. Pass ID, name of the form, the entire CONTROL that
// sits IN the form, and the form name again.
// The form name is the container.
SaveControl(ID, sFormName, formControl, sFormName);
}
}
}
In the SaveControl-method, I can easily work with the control. For example, I can write:
sControlValue = ControlToSave.Text;
…to get the control's Text-property.
When opening the form I first need to create the hashtable of controls, so I can get at their index-values! The following method returns a hashtable with all controls in a form:
public Hashtable GetControls(Form form)
{
Hashtable formControlsHash = new Hashtable();
int formControlIndex;
int panelControlIndex;
string formControlName;
string panelControlName;
// Populate SmartControls with forms controls.
foreach (Control formControl in form.Controls)
{
// Get index of formControl
formControlIndex = form.Controls.IndexOf(formControl);
// Get name of control.
formControlName = formControl.Name;
// Add control to hashtable
formControlsHash.Add(formControlName, formControlIndex);
if (formControl.GetType().ToString() == "System.Windows.Forms.Panel")
{
// Loop through controls in panel
foreach (Control panelControl in form.Controls[formControlIndex].Controls)
{
// Get index of current panelControl
panelControlIndex = form.Controls[formControlIndex].Controls.IndexOf(panelControl);
// Get name of panelControl. Name is constructed as "formControlName.panelControlName"
panelControlName = formControlName + "." + panelControl.Name;
// Add control to listbox
formControlsHash.Add(panelControlName, panelControlIndex);
}
}
}
return formControlsHash;
}
The ControlName is fetched from the database and since it contains any panel-name (if the control sits in a panel), then I can get their index-values from the hashtable. Note the lines of code that are made bold:
int delimeterPosition = sControlName.IndexOf(".", 0);
// If delimeter is found, then get container name also
if (delimeterPosition > 0)
{
// Container is not the form
controlName = sControlName.Substring(delimeterPosition + 1);
containerName = sControlName.Substring(0, delimeterPosition);
// Get the index of the container
indexOfContainer = (int)formControlsHash[containerName];
// Get the index of the control
indexOfControl = (int)formControlsHash[sControlName];
// Get the control
controlToSet = Form.Controls[indexOfContainer].Controls[indexOfControl];
// Set sControlName to be the new name, after having peeled of the container name.
sControlName = controlName;
}
else
{
// Get the index of the control
indexOfControl = (int)formControlsHash[sControlName];
// Get the control
controlToSet = Form.Controls[indexOfControl];
}
Now, I have a control that I can work with and set its value!