Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

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:

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

  • Leaders
Posted

I haven't tried this, but can it be done using reflection?

(Imports System.Reflection)

   Dim Assm As [Assembly] = _
       [Assembly].GetExecutingAssembly
   Dim Control As Object = Assm.CreateInstance("Namespace.TypeName")
   'TypeName must be fully qualified

[sIGPIC]e[/sIGPIC]
Posted

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.

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?

Posted
That's because there's no System.Window.Forms.Button in your executing assembly. You need to use CreateInstance on the WindowsForms assembly.
"Who is John Galt?"
Posted
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.

For questions about VS .net extensibility, please fire at me! :)

For readability, please use the [ CS][/CS ] tags

Posted
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:

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. :-\

  • *Experts*
Posted

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):

//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.

Posted
//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

Posted

Apololgies if I wasn't clear in the first case.

 

I have a call to a database something like this:

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:

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

  • *Experts*
Posted

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):

//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);

Posted
MyControl myctrl = (MyControl)asmb.CreateInstance(ctrlname' date=' 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".
  • *Experts*
Posted
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 :).
Posted

But problem no. 1 here:

From my point of view davearia uses VB .net, that doesn't allow typecasting. Away solution...

For questions about VS .net extensibility, please fire at me! :)

For readability, please use the [ CS][/CS ] tags

  • Leaders
Posted

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, USN

One of my coworkers thinks that I believe that drawing bullets is the most efficient way of drawing bullets. Whatever!!! :-(

Posted
:o Because my VB proficiency is way lower than my C# proficiency

For questions about VS .net extensibility, please fire at me! :)

For readability, please use the [ CS][/CS ] tags

Posted

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

Posted
But problem no. 1 here:

From my point of view davearia uses VB .net, that doesn't allow typecasting. Away solution...

Oh you disbelievers..... are there still people out there who don't believe that VB has grown up long time ago!? :p

 

There is even a second way of type casting. It's the method CType. :cool:

  • Leaders
Posted
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

I merely converted mutant's C# code to VB.NET. From the looks of it, it creates something from within the assembly that you have to convert to a control, but I won't profess to knowing exactly what it is. :)

Iceplug, USN

One of my coworkers thinks that I believe that drawing bullets is the most efficient way of drawing bullets. Whatever!!! :-(

  • *Experts*
Posted

Here is an equivalent for you:

The DirectCast call will convert the created object into a control for you.

Dim ctrlname As String = "WindowsApplication1.myctrl"

Dim asmb As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim ctrl As UserControl = DirectCast(asmb.CreateInstance(ctrlname, False), UserControl)

Posted
This is all a question of how to use basic reflection, which .NET supports wonderfully. Just a meander thru the System.Reflection namespace should yield answers. The many Assembly.Load* functions should give you an idea of how to access system assemblies.
"Who is John Galt?"
Posted

Many thanks for your help.

 

Here is what I used:

Dim ctrlname As String = "ctlMyControl"
Dim asmb As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom("C:\MyDLL.dll")
Dim ctrl As UserControl = DirectCast(asmb.CreateInstance(ctrlname, False), UserControl)
Me.pnl.Controls.Add(ctrl)

 

The only thing I needed to change from the code provided was the assembly reference as the reference is a dll outside the current assembly.

 

Thanks to everyone again you are brilliant.

 

Thanks, Dave. :D :D :D

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...