Dynamically creation of control  
Author Message
bachie





PostPosted: Visual C# General, Dynamically creation of control Top

This is the sample code:

public void GetControlArray(ref CommandButton[] btArray, string ArrayName) {}
public void GetControlArray(ref CheckBox[] btArray, string ArrayName) {}
public void GetControlArray(ref ThirdPartyTextBox[] btArray, string ArrayName) {}
public void GetControlArray(ref RadioButton[] btArray, string ArrayName)
{
 if (btArray == null)
 {
  int i=0;
  tempArray = new ArrayList();
  GetControlArray(this, ArrayName, "System.Windows.Forms.RadioButton");
  btArray = new RadioButton[tempArray.Count];
  foreach(RadioButton rb in tempArray)
  {
   btArray[i++] = rb;
  }
 }
}

Color Green: change to object
Color Orange:
I need to dynamically change based on the object type.

My goal is to eliminate the other redundant method of GetControlArray and make it only one method to maintain. Please help me.

Thank you very much.

 

-Bachie




Visual C#13  
 
 
TaylorMichaelL





PostPosted: Visual C# General, Dynamically creation of control Top

Firstly I'm assuming that you are using v2.0. Secondly I'm going to morph your function a little bit.

public T[] GetControlArray<T> ( string arrayName )
{
int i = 0;
ArrayList list = GetControlArray(this, arrayName, typeof(T).FullName);
T[] arr = new T[list.Length];
foreach(object obj in list)
{
arr[++i] = (T)obj;
};

return arr;
}

If you prefer to avoid generics or you are using v1.1 then the following solution works as well.

public Control[] GetControlArray ( Type controlType, string arrayName )
{
int i = 0;
ArrayList list = GetControlArray(this, arrayName, controlType.FullName);
Control[] arr = new Control[list.Length];
foreach(Control ctrl in list)
arr[++i] = ctrl;

return arr;
}

Notice that in both cases I'm moving away from generic (as in general) definitions in lieu of strongly typed values to help catch issues at compile time. In both cases if the returned objects don't match what you thought they were you'll get an exception. It would be nice if the internal GetControlArray method returned a control collection rather than an ArrayList.

Michael Taylor - 11/29/06


 
 
bachie





PostPosted: Visual C# General, Dynamically creation of control Top

I have compilation error at the same set of codes.

At Line 4: It says that Error 38 type 'void' cannot be converted into type

At Line 5: It says that Error 39 'Length' is not defined

I think we need to post here the other supported codes:

The scenario is: I converted a VB6 proj to VB.NET2005 using upgrade wizard then paste all controls to C#.NET2005. I've noticed that all of my array of OptionButton was converted to RadioButton with renamed into _VB6ControlName_0...._1..._2..._3 and not array of controls anymore.

.NET2005 was automatically created a component to support that functionality but using the MS VB Compatibility. I don't want to use that, therefore I need to create on my own.

private System.Collections.ArrayList tempArray;
private Button[] cmdShori;
private RadioButton[] optModeKbn;
private RadioButton[] optInputKbn;
private void GetControlArray(Control ctl, string strName, String type)
{
int iIndex = 0;
foreach (Control control in ctl.Controls)
{
if (control.Name.IndexOf(strName) >= 0)
{
if (control.Name.IndexOf("_") >= 0)
{
if (IsNumeric(control.Name.Substring(control.Name.LastIndexOf('_') + 1)))
{
iIndex = System.Convert.ToInt32(control.Name.Substring(control.Name.LastIndexOf('_') + 1));
if (control.GetType().ToString() == type)
{
//search for "_" to determine if it was an array of radiobuttons
if (control.Name.IndexOf("_") >= 0)
{
AddToList(ref tempArray, iIndex);
tempArray[iIndex] = control;
}
}
}
}
}
if (control.HasChildren)
{
GetControlArray(control, strName, type);
}
}
}

//gets the array of RadioButton controls
public void GetControlArray(ref RadioButton[] btArray, string ArrayName)
{
if (btArray == null)
{
int i = 0;
tempArray = new System.Collections.ArrayList();
GetControlArray(this, ArrayName, "System.Windows.Forms.RadioButton");
btArray = new RadioButton[tempArray.Count];
foreach (RadioButton rb in tempArray)
{
btArray[i++] = rb;
}
}
}

public int GetIndex(string Name)
{
int Index = 0;
if (Name.IndexOf("_") >= 0)
{
if (IsNumeric(Name.Substring(Name.LastIndexOf("_") + 1)))
{
Index = Convert.ToInt32(Name.Substring(Name.LastIndexOf("_") + 1));
}
}
return Index;
}

void AddToList(ref System.Collections.ArrayList arr, int iIndex)
{
if (arr.Count <= iIndex)
{
for (int i = arr.Count; i <= iIndex; i++)
{
arr.Add(null);
}
}
}



 
 
TaylorMichaelL





PostPosted: Visual C# General, Dynamically creation of control Top

The posted code was in answer to your original question about how to reduce the maintenance of the original code. Other than a couple of compilation issues (like changing Length to Count) it'll work. However that does nothing for your migration efforts. Exactly what are you trying to accomplish in your code All I can determine is that you're separating controls into different arrays based on type but I don't know why you'd ever do this. The Controls property of your form will contain all the top-level controls on the form. You can enumerate this collection and simply do a typecheck to find specific control types if you truly want to separate them out.

private T[] GetControlArray<T> ( Control.ControlCollection controls, bool recurse ) where T : Control
{
Type typeControl = typeof(T);
Collection<T> coll = new Collection<T>();

foreach (Control ctrl in controls)
{
if (ctrl.GetType() == typeControl)
coll.Add((T)ctrl);

if (recurse && ctrl.HasChildren)
{
foreach (T child in GetControlArray<T>(ctrl.Controls, true))
coll.Add(child);
};
};

T[] arr = new T[coll.Count];
coll.CopyTo(arr,
0);
return arr;
}

The above method will return an array (again you should prefer return values to ref parameters whenever possible) of controls of a specific type. Optionally you can return any child controls of the top-level controls as well. You might use this as follows.

protected override void OnLoad ( EventArgs e )
{
base.OnLoad(e);

foreach (TextBox box in GetControlArray<TextBox>(Controls, true))
Debug.WriteLine(box.Name);
}

The above method (invoked when the form loads) dumps all the textboxes (in containers or otherwise) to the output window.

Michael Taylor - 11/30/06