Reputation: 841
I have an aspx page that I would like to have injected a reference to a user control. The user control is stored in a seperate assembly and loaded at runtime. After injected the user control it should then be loaded into the control collection of the page.
Everything seems to be working fine expect the point of adding the control to the page. There is no error but the UI for the control doesn't show.
global.asax.cs
protected override Ninject.IKernel CreateKernel()
{
var modules = new INinjectModule[] { new MyDefaultModule() };
var kernel = new StandardKernel(modules);
// Loads the module from an assembly in the Bin
kernel.Load("ExternalAssembly.dll");
return kernel;
}
and here is how the external module is defined in the other assembly:
public class ExternalModule : NinjectModule
{
public ExternalModule() { }
public override void Load()
{
Bind<IView>().To<controls_MyCustomUserControlView>();
}
}
The debugger shows that when the app is run, the Load on the external module is being called, and the dependency gets injected into the page.
public partial class admin_MainPage : PageBase
{
[Inject]
public IView Views { get; set; }
At this point when trying to add the view (here a user control) to the page, nothing is shown. Is this something to do with the way the user control is created by Ninject? The loaded control seems to have an empty control collection.
inside aspx page
var c = (UserControl)Views;
// this won't show anything. even the Control collection of the loaded control (c.Controls) is empty
var view = MultiView1.GetActiveView().Controls.Add(c);
// but this works fine
MultiView1.GetActiveView().Controls.Add(new Label() { Text = "Nice view you got here..." });
and finally the view/user control:
public partial class controls_MyCustomUserControlView : UserControl, IView
{
}
It contains just one label:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>
<asp:Label Text="Wow, what a view!" runat="server" />
Upvotes: 3
Views: 1657
Reputation: 841
Been able to get this working by calling Page.LoadControl with the user control as a resource.
Page.LoadControl(typeof(controls_controls_MyCustomUserControlView), null) does not work, however Page.LoadControl("controls_MyCustomUserControlView.ascx") does.
As the control is in an external assembly, first create a VirtualPathProvider and VirtualFile as discussed http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx
The custom VirtualPathProvider will be used to check if the user control is located in an external assembly, and the VirtualFile (user control) will get returned as a resource from the assembly.
Next setup the Ninject module to load the user control:
public override void Load()
{
//Bind<IView>().To<controls_MyCustomUserControlView>();
Bind<IView>().ToMethod(LoadControl).InRequestScope();
}
protected IView LoadControl(Ninject.Activation.IContext context)
{
var page = HttpContext.Current.Handler as System.Web.UI.Page;
if (page != null)
{
//var control = page.LoadControl(typeof(controls_MyCustomUserControlView), null);
var control = page.LoadControl("~/Plugins/ExternalAssembly.dll/MyCustomUserControlView.ascx");
return (IView)control;
}
return null;
}
"Plugins" is just a prefix for determining in the VirtualPathProvider if the control is located in another assembly.
If your user control has a namespace then make sure you prefix the control name in LoadControl. The other thing is making sure to use CodeBehind instead of CodeFile as ASP.NET will try load a CodeBehind file.
<%@ Control Language="C#" AutoEventWireup="true"
CodeBehind="~/MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>
Upvotes: 2