Adding user controls at runtime using string

davearia

Centurion
Joined
Jan 4, 2005
Messages
184
Hi All,

I have an application that queries a table to return the name of user controls that I have in my application. I want to use this to create the controls dynamically at runtime.

So I have my results stored in ds.Tables("myTable") and it returns a resulting VarChar ctlMyControl.

Normally you would create and add it to the form like this:
Visual Basic:
Private ctl As New ctlMyControl
Me.pnl.Controls.Add(ctl)
How do I create this control in my code using the results returned from the query?

Thanks, Dave. :D :D :D
 
I haven't tried this, but can it be done using reflection?
Visual Basic:
(Imports System.Reflection)
 
    Dim Assm As [Assembly] = _
        [Assembly].GetExecutingAssembly
    Dim Control As Object = Assm.CreateInstance("Namespace.TypeName")
    'TypeName must be fully qualified
 
Sorry marble eater, I think this won't work either (in fact I tried it, because I wanted to know). ;)

I know another way (which doesn't work in this case either :D ) where you don't even have to import the Reflection namespace.
Visual Basic:
Dim vType As Type = Type.GetType("System.Windows.Forms.Button")
Dim vInstance As Object = Activator.CreateInstance(vType)
The problem is that the CreateInstance method of the Assembly class as well as the GetType method of the Type class, expects a System.Type.Fullname. And as you can try with "System.Windows.Forms.Button" which is the fullname of a button's type you get an objectreference of nothing. So it seems that these methods only work with classes of your own assemblies ("Projectnamespace.Classname").

That's strange. :confused: Any idea?
 
Has anyone got anymore ideas?

Thanks for the help so far. :D

Has anyone got anymore ideas?

Thanks, Dave. :D :D
 
I don't think it would be possible. You could never deceive the compiler in using a field for a class constructor. I would put my hope into a Switch statement and just call the constructors with the parameters from the database.
 
IngisKahn said:
You need to use CreateInstance on the WindowsForms assembly.
Can you be more specific. What do you gain by that and what are the next steps after that?

Well to be honest, I think we all try to find a perfect and elegant solution to devearia's problem. So we look for a solution with the highest degree of freedom. But as long as we can't provide a "perfect" solution we should give any solution that resolves the problem for the moment.

I would say there is a "quick and dirty" one on that. Supposing that a record of the table contains the fields, that describe the properties of a control, there is one field that contains the type of it. Then devearia could do the following:
Visual Basic:
For Each r as DataRow in ControlTable.Rows
  Select Case r("CtrlType").ToString
    Case "Button"
       Dim B as New Button
       'assign all properties and handlers
       Me.Controls.Add(B)
       B = Nothing
    Case "TextBox"
      'and so on
  End Select
Next
Not really elegant and very, very stiff, but for the moment it will do. Meanwhile we are looking for a better solution. :-\
 
I don't get what everyone is having problems with :), but simple reflection work solves this problem (let's take a look at the button for example):
C#:
//First we get the required assembly.
Assembly btnassembly = Assembly.GetAssembly(typeof(System.Windows.Forms.Button));
//And then simply create the button.
Button btn = (Button)btnassembly.CreateInstance("System.Windows.Forms.Button", false);
Unless I'm missing something from your problem (and other posts), this should work on any assembly.
 
mutant said:
C#:
//First we get the required assembly.
Assembly btnassembly = Assembly.GetAssembly(typeof(System.Windows.Forms.Button));
//And then simply create the button.
Button btn = (Button)btnassembly.CreateInstance("System.Windows.Forms.Button", false);
But there you can see it again; as far as we came until now, there seems to be no way to have a functionality without particularly coding all eventualities that might occur during runtime. "typeof(System.Windows.Forms.Button)" can't be represented by a string variable (as well as the following type casting). And that seems to be the point to me, but maybe I am missing it too. :)

But maybe davearia could light the darkness, if he tells us what he exactly wants to do in his program. :D
 
Apololgies if I wasn't clear in the first case.

I have a call to a database something like this:
Code:
SELECT ctlName FROM ctlTable_T WHERE ctlID = @usersChoice
There could be hundreds of user control's names stored in this table (which is why I am avoiding a "case statement fudge" like the plague), all of these user controls are in my solution. At runtime the results of this query are stored in a dataset ds.

So we could have ds.Tables("ctlControls"). In the dataset we only one result, a VarChar which could be say ctlMyControl, there is a user control with this name which exists in the solution.

We could say for example assign this result from the dataset to a string:
Visual Basic:
Dim str As String = ds.Tables("ctlControls").Rows(0).Item(0).ToString
How do I at runtime use the results in the dataset assigned to str to dynamically create the instance of this control.

I hope I have been clearer this time, thanks again for your help.

Thanks, Dave. :D :D :D
 
As I see it this will work excatly the way you want, as suggested previously by marble_eater (assuming your controls are in the same assembly as your program):
C#:
//Replace the hardcoded string with your string you get from db.
string ctrlname = "WindowsApplication2.MyControl";

Assembly asmb = Assembly.GetExecutingAssembly();
MyControl myctrl = (MyControl)asmb.CreateInstance(ctrlname, false);
 
mutant said:
MyControl myctrl = (MyControl)asmb.CreateInstance(ctrlname, false);[/CODE]
This assumes that davearia only has one type of controls in his assembly. But if he has more than one, it seems to be impossible to avoid "case statement fudging".
 
MyControl can simply be a base type for all other usercontrols he creates (or even cast it to a UserControl, it doesn't matter). Either way it works for what he seems to be requiring. Can't forget some level of abstraction :).
 
Sure you can do typecasting in VB by way of DirectCast. Why would you think that VB can't do this?

myctrl = DirectCast(asmb.CreateInstance(ctrlname, false), myControl)
:)
 
IcePlug can you please elaborate just a bit more with your code.

I have a resulting String str which holds the name of the control we are going to create. How exactly am I going to use this to create an instance of this control.

Many thanks in anticipation. :D
 
Back
Top