473,405 Members | 2,445 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Instantiate/Load UserControl from DLL

Hi there,

I searched carefully through the web before finally deciding to post
this message, because I could not find a solution for my problem.
Hopefully someone will have a hint or explanation for me! I apologize
for the length of this posting, but I wanted to make sure that I get an
answer other than "Hey man, just use LoadControl!", because this is not
what I want.

The Task: Isolate a collection of web forms which are created as
UserControls from the web application framework so that they can be
easily changed, exchanged, removed, and added, without having to
restart or recompile the web application.
My Approach: Store UserControls in separate project and dynamically
load assembly. Example code in C#:

[... Code Snippet Begin ...]
ObjectHandle PackageManagerHandle;
IPackageManager packageManager;

// Load Assembly
PackageManagerHandle = Activator.CreateInstanceFrom("Packages.dll",
"Packages.PackageManager");

// Unwrap type
packageManager = (IPackageManager) PackageManagerHandle.Unwrap();
UserControl control = packageManager.GetControl(ctrlName);
control.InitializeAsUserControl(this.Page);
[... Code Snippet End ...]

This is pretty much the same code that can be found in MSDN when
looking at Assembly.LoadFrom or Activator.CreateInstance. The
interesting part are the last two lines, where the actual UserControl
instance is created. The very last line came from the very informative
article at http://aspalliance.com/399 about LoadControl and
LoadTemplate, but actually does not change much for me.

The Result: When I execute the above code, it works fine and I get an
instance of my UserControl, but all the controls inside of the
UserControl are not initialized, therefore it shows up on the page as
an empty control. This seems to make sense, though, because the
instantiation only creates an instance of the UserControl class, but it
does not execute/interpret the actual ascx file that has the HTML code
in it.

Why not use Page.LoadControl? Here is why: First of all, LoadControl
expects a virtual path to the ascx file of the UserControl. This means
the ascx file has to be inside of the web root of that web application,
and I cannot compile it into my single DLL, which would be much nicer
to deploy and maintain.

While trying different things out, I found two solutions, which I
briefly want to present here:

Solution 1: Go back to using Page.LoadControl, but still call it from
my PackageManager class which is in another project (or solution, for
that matter) than my web application.
Advantage: It works!
Disadvantage: I need to have my user control files somewhere in the web
root of the application, otherwise LoadControl cannot find them. Also,
the type the UserControl inherits from needs to be known to the
assembly, otherwise I get an ugly Cannot Load Type error. As I said, it
works, but I was hoping for a more elegant solution.

Solution 2: While trying to overcome the fact that simply instantiating
the UserControl does not evaluate the ascx file I thought about using
ParseControl, which I usually don't like very much since it does not
compile or interpret any code. However, in this case this is exactly
what I want, because I already have my UserControl instance and all I
need are the controls inside of my UserControl instantiated with the
parameters specified in the HTML tags in the ascx file.
Here is how it works: First I create the UserControl instance, then I
use ParseControl to parse the ascx file into a control. Next I add this
parsed control to my user control. Here comes the tricky part:
Unfortunately I don't know what exactly is going on behind the scenes
if you instantiate a UserControl just by dropping it on to a page in
Visual Studio, but the key part is that ASP.NET connects the controls
in the ascx file with the protected member variables in the code
behind. This connection is somehow lost in the way I do it, so that
trying to access a server control from the code behind causes a Object
Not Set To An Instance exception.
I found a solution for this as well: By using Reflection I iterated
over the Fields collection of the UserControl and then used FindControl
to find the respective server controls in the Controls collection. This
way I could reconnect the code behind with the "code in front".
This is a short code snippet which illustrates this solution:

[... Code Snippet Begin ...]
StreamReader sr = new StreamReader(fileName);
Control parseControl = Container.Page.ParseControl(sr.ReadToEnd());
sr.Close();

userControl.Controls.Add(parseControl);
Type type = userControl.GetType();
System.Reflection.FieldInfo[] fields =
type.GetFields(System.Reflection.BindingFlags.Inst ance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.DeclaredOnly);
foreach ( System.Reflection.FieldInfo field in fields )
{
Control ctrl = FindControlQ(userControl, field.Name);
field.SetValue(userControl, ctrl);
}
[... Code Snippet End ...]

The first three lines read the ascx file through a stream reader. This
has the HUGE advantage of being able to put the UserControl files
anywhere, not necessarily inside of the web root of the web
application.
Note that I am using FindControlQ which is a recursive version of
FindControl, so that controls nested in other NamingContainers are
found as well.
Despite the fact that I have actually two working solutions now, I am
left with two questions:
1. Is there an easier way to do this? The first code snippet at the
beginning of this posting seems to do *almost* what I want, so maybe I
am just missing a simple call which would save me all the ParseControl
and Reflection work? All I am doing is more or less mimicing the
behavior of LoadControl, so if there was a different way to execute
LoadControl on a file outside of the web root, that would work fine for
me.
2. Are there any reasons why going down that ParseControl/Reflection
path might cause serious problems later? I tested my solution with a
couple of UserControls, and it seems that ViewState, Validators etc.
are still working correctly, and my events in the code behind are
firing as I expect it.
Thanks for reading through all this, I'd be happy about feedback, and
if someone out there happens to find a solution for his or her problem
in this posting, feel free to ask any questions, I can also post more
code if necessary!

Thanks,
Sascha

Nov 19 '05 #1
2 4575

Would you mind giving out the code for FindControlQ?

Sascha wrote:
*Hi there,

I searched carefully through the web before finally deciding to post
this message, because I could not find a solution for my problem.
Hopefully someone will have a hint or explanation for me! I
apologize
for the length of this posting, but I wanted to make sure that I get
an
answer other than "Hey man, just use LoadControl!", because this is
not
what I want.

The Task: Isolate a collection of web forms which are created as
UserControls from the web application framework so that they can be
easily changed, exchanged, removed, and added, without having to
restart or recompile the web application.
My Approach: Store UserControls in separate project and dynamically
load assembly. Example code in C#:

[... Code Snippet Begin ...]
ObjectHandle PackageManagerHandle;
IPackageManager packageManager;

// Load Assembly
PackageManagerHandle = Activator.CreateInstanceFrom("Packages.dll",
"Packages.PackageManager");

// Unwrap type
packageManager = (IPackageManager) PackageManagerHandle.Unwrap();
UserControl control = packageManager.GetControl(ctrlName);
control.InitializeAsUserControl(this.Page);
[... Code Snippet End ...]

This is pretty much the same code that can be found in MSDN when
looking at Assembly.LoadFrom or Activator.CreateInstance. The
interesting part are the last two lines, where the actual
UserControl
instance is created. The very last line came from the very
informative
article at http://aspalliance.com/399 about LoadControl
and
LoadTemplate, but actually does not change much for me.

The Result: When I execute the above code, it works fine and I get
an
instance of my UserControl, but all the controls inside of the
UserControl are not initialized, therefore it shows up on the page
as
an empty control. This seems to make sense, though, because the
instantiation only creates an instance of the UserControl class, but
it
does not execute/interpret the actual ascx file that has the HTML
code
in it.

Why not use Page.LoadControl? Here is why: First of all, LoadControl
expects a virtual path to the ascx file of the UserControl. This
means
the ascx file has to be inside of the web root of that web
application,
and I cannot compile it into my single DLL, which would be much
nicer
to deploy and maintain.

While trying different things out, I found two solutions, which I
briefly want to present here:

Solution 1: Go back to using Page.LoadControl, but still call it
from
my PackageManager class which is in another project (or solution,
for
that matter) than my web application.
Advantage: It works!
Disadvantage: I need to have my user control files somewhere in the
web
root of the application, otherwise LoadControl cannot find them.
Also,
the type the UserControl inherits from needs to be known to the
assembly, otherwise I get an ugly Cannot Load Type error. As I said,
it
works, but I was hoping for a more elegant solution.

Solution 2: While trying to overcome the fact that simply
instantiating
the UserControl does not evaluate the ascx file I thought about
using
ParseControl, which I usually don't like very much since it does not
compile or interpret any code. However, in this case this is exactly
what I want, because I already have my UserControl instance and all
I
need are the controls inside of my UserControl instantiated with the
parameters specified in the HTML tags in the ascx file.
Here is how it works: First I create the UserControl instance, then
I
use ParseControl to parse the ascx file into a control. Next I add
this
parsed control to my user control. Here comes the tricky part:
Unfortunately I don't know what exactly is going on behind the
scenes
if you instantiate a UserControl just by dropping it on to a page in
Visual Studio, but the key part is that ASP.NET connects the
controls
in the ascx file with the protected member variables in the code
behind. This connection is somehow lost in the way I do it, so that
trying to access a server control from the code behind causes a
Object
Not Set To An Instance exception.
I found a solution for this as well: By using Reflection I iterated
over the Fields collection of the UserControl and then used
FindControl
to find the respective server controls in the Controls collection.
This
way I could reconnect the code behind with the "code in front".
This is a short code snippet which illustrates this solution:

[... Code Snippet Begin ...]
StreamReader sr = new StreamReader(fileName);
Control parseControl = Container.Page.ParseControl(sr.ReadToEnd());
sr.Close();

userControl.Controls.Add(parseControl);
Type type = userControl.GetType();
System.Reflection.FieldInfo[] fields =
type.GetFields(System.Reflection.BindingFlags.Inst ance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.DeclaredOnly);
foreach ( System.Reflection.FieldInfo field in fields )
{
Control ctrl = FindControlQ(userControl, field.Name);
field.SetValue(userControl, ctrl);
}
[... Code Snippet End ...]

The first three lines read the ascx file through a stream reader.
This
has the HUGE advantage of being able to put the UserControl files
anywhere, not necessarily inside of the web root of the web
application.
Note that I am using FindControlQ which is a recursive version of
FindControl, so that controls nested in other NamingContainers are
found as well.
Despite the fact that I have actually two working solutions now, I
am
left with two questions:
1. Is there an easier way to do this? The first code snippet at the
beginning of this posting seems to do *almost* what I want, so maybe
I
am just missing a simple call which would save me all the
ParseControl
and Reflection work? All I am doing is more or less mimicing the
behavior of LoadControl, so if there was a different way to execute
LoadControl on a file outside of the web root, that would work fine
for
me.
2. Are there any reasons why going down that ParseControl/Reflection
path might cause serious problems later? I tested my solution with a
couple of UserControls, and it seems that ViewState, Validators etc.
are still working correctly, and my events in the code behind are
firing as I expect it.
Thanks for reading through all this, I'd be happy about feedback,
and
if someone out there happens to find a solution for his or her
problem
in this posting, feel free to ask any questions, I can also post
more
code if necessary!

Thanks,
Sascha *
Would you mind giving out the code for FindControlQ?


--
msteller
------------------------------------------------------------------------
Posted via http://www.codecomments.com
------------------------------------------------------------------------

Apr 15 '06 #2

Did you manage to find out a solution?
I got exactly the same problem

Best Regards
Franz Thomsen

Sascha wrote:
*Hi there,

I searched carefully through the web before finally deciding to post
this message, because I could not find a solution for my problem.
Hopefully someone will have a hint or explanation for me! I
apologize
for the length of this posting, but I wanted to make sure that I get
an
answer other than "Hey man, just use LoadControl!", because this is
not
what I want.

The Task: Isolate a collection of web forms which are created as
UserControls from the web application framework so that they can be
easily changed, exchanged, removed, and added, without having to
restart or recompile the web application.
My Approach: Store UserControls in separate project and dynamically
load assembly. Example code in C#:

[... Code Snippet Begin ...]
ObjectHandle PackageManagerHandle;
IPackageManager packageManager;

// Load Assembly
PackageManagerHandle = Activator.CreateInstanceFrom("Packages.dll",
"Packages.PackageManager");

// Unwrap type
packageManager = (IPackageManager) PackageManagerHandle.Unwrap();
UserControl control = packageManager.GetControl(ctrlName);
control.InitializeAsUserControl(this.Page);
[... Code Snippet End ...]

This is pretty much the same code that can be found in MSDN when
looking at Assembly.LoadFrom or Activator.CreateInstance. The
interesting part are the last two lines, where the actual
UserControl
instance is created. The very last line came from the very
informative
article at http://aspalliance.com/399 about LoadControl
and
LoadTemplate, but actually does not change much for me.

The Result: When I execute the above code, it works fine and I get
an
instance of my UserControl, but all the controls inside of the
UserControl are not initialized, therefore it shows up on the page
as
an empty control. This seems to make sense, though, because the
instantiation only creates an instance of the UserControl class, but
it
does not execute/interpret the actual ascx file that has the HTML
code
in it.

Why not use Page.LoadControl? Here is why: First of all, LoadControl
expects a virtual path to the ascx file of the UserControl. This
means
the ascx file has to be inside of the web root of that web
application,
and I cannot compile it into my single DLL, which would be much
nicer
to deploy and maintain.

While trying different things out, I found two solutions, which I
briefly want to present here:

Solution 1: Go back to using Page.LoadControl, but still call it
from
my PackageManager class which is in another project (or solution,
for
that matter) than my web application.
Advantage: It works!
Disadvantage: I need to have my user control files somewhere in the
web
root of the application, otherwise LoadControl cannot find them.
Also,
the type the UserControl inherits from needs to be known to the
assembly, otherwise I get an ugly Cannot Load Type error. As I said,
it
works, but I was hoping for a more elegant solution.

Solution 2: While trying to overcome the fact that simply
instantiating
the UserControl does not evaluate the ascx file I thought about
using
ParseControl, which I usually don't like very much since it does not
compile or interpret any code. However, in this case this is exactly
what I want, because I already have my UserControl instance and all
I
need are the controls inside of my UserControl instantiated with the
parameters specified in the HTML tags in the ascx file.
Here is how it works: First I create the UserControl instance, then
I
use ParseControl to parse the ascx file into a control. Next I add
this
parsed control to my user control. Here comes the tricky part:
Unfortunately I don't know what exactly is going on behind the
scenes
if you instantiate a UserControl just by dropping it on to a page in
Visual Studio, but the key part is that ASP.NET connects the
controls
in the ascx file with the protected member variables in the code
behind. This connection is somehow lost in the way I do it, so that
trying to access a server control from the code behind causes a
Object
Not Set To An Instance exception.
I found a solution for this as well: By using Reflection I iterated
over the Fields collection of the UserControl and then used
FindControl
to find the respective server controls in the Controls collection.
This
way I could reconnect the code behind with the "code in front".
This is a short code snippet which illustrates this solution:

[... Code Snippet Begin ...]
StreamReader sr = new StreamReader(fileName);
Control parseControl = Container.Page.ParseControl(sr.ReadToEnd());
sr.Close();

userControl.Controls.Add(parseControl);
Type type = userControl.GetType();
System.Reflection.FieldInfo[] fields =
type.GetFields(System.Reflection.BindingFlags.Inst ance |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.DeclaredOnly);
foreach ( System.Reflection.FieldInfo field in fields )
{
Control ctrl = FindControlQ(userControl, field.Name);
field.SetValue(userControl, ctrl);
}
[... Code Snippet End ...]

The first three lines read the ascx file through a stream reader.
This
has the HUGE advantage of being able to put the UserControl files
anywhere, not necessarily inside of the web root of the web
application.
Note that I am using FindControlQ which is a recursive version of
FindControl, so that controls nested in other NamingContainers are
found as well.
Despite the fact that I have actually two working solutions now, I
am
left with two questions:
1. Is there an easier way to do this? The first code snippet at the
beginning of this posting seems to do *almost* what I want, so maybe
I
am just missing a simple call which would save me all the
ParseControl
and Reflection work? All I am doing is more or less mimicing the
behavior of LoadControl, so if there was a different way to execute
LoadControl on a file outside of the web root, that would work fine
for
me.
2. Are there any reasons why going down that ParseControl/Reflection
path might cause serious problems later? I tested my solution with a
couple of UserControls, and it seems that ViewState, Validators etc.
are still working correctly, and my events in the code behind are
firing as I expect it.
Thanks for reading through all this, I'd be happy about feedback,
and
if someone out there happens to find a solution for his or her
problem
in this posting, feel free to ask any questions, I can also post
more
code if necessary!

Thanks,
Sascha *


--
Franz Thomsen
------------------------------------------------------------------------
Posted via http://www.codecomments.com
------------------------------------------------------------------------

May 11 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: keith | last post by:
I have a win app that will load a usercontrol which is in a dll file, e.g. UserControl1.dll. The UserControl1.dll refers another usercontrol which is in another dll file, e.g. UserControl2.dll. ...
4
by: sebastien | last post by:
Hi, In page_load : If Not Page.IsPostBack Then Dim myUC As UserControl = LoadControl("ficheProspects.ascx") myUC.ID = "FicheProspects1" End If In another Sub i need to find my control :
1
by: Matteo Migliore | last post by:
Hi. This is a question about ASP.NET 2.0. How can I instantiate a UserControl without the method LoadControl? I need to create a usercontrol from a .ascx file that is out of the web...
12
by: Joe | last post by:
Hello All: Do I have to use the LoadControl method of the Page to load a UserControl? I have a class which contains three methods (one public and two private). The class acts as a control...
1
by: Stan SR | last post by:
Hi, With asp.net 2, c# I try to load UserControl on "fly". When I test the website using VS2005, everything works. When I try to publish the website, I get some errors like : "The type or...
0
by: ush | last post by:
while dynamically loading usercontrol I am getting the errror - ' type 'ImageButton' must be placed inside a form tag with runat=server '. how to solve this - if a usercontrol contains...
2
by: Nick | last post by:
I have two navigation user controls and based on a query string will load one or the other. On the page that will load the user control I cannot do the following Dim uc As FlashNavigation (The...
2
by: Merk | last post by:
I'm wanting to know if/how it would be possible to load a form based on a string that contains the name of the form (class). For example, instead of doing this: myForm f = new myForm();...
1
by: mAbZ | last post by:
I neeed to instantiate an UserControl in an aspx page like this: <MyNamespace:MyControl ID="ctrl1" runat="server" MyParent="<%# this %>" /> where "this" is the current aspx page and should be...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.