在WebForms中使用Ninject注入Web用户控件

时间:2010-12-16 17:29:08

标签: asp.net webforms ninject

我有一个aspx页面,我想要注入一个用户控件的引用。用户控件存储在单独的程序集中并在运行时加载。注入用户控件后,应将其加载到页面的控件集合中。

一切似乎工作正常,期望将控件添加到页面。没有错误,但控件的UI未显示。

的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;
}

以下是外部模块在另一个程序集中的定义方式:

public class ExternalModule : NinjectModule
{
    public ExternalModule() { }
    public override void Load()
    {
        Bind<IView>().To<controls_MyCustomUserControlView>();
    }
}

调试器显示当应用程序运行时,正在调用外部模块上的Load,并将依赖项注入页面。

public partial class admin_MainPage : PageBase
{
    [Inject]
    public IView Views { get; set; }

此时尝试将视图(此处为用户控件)添加到页面时,不会显示任何内容。这与Ninject创建用户控件的方式有关吗?加载的控件似乎有一个空的控件集合。

在aspx页面内

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..." });  

最后是视图/用户控件:

public partial class controls_MyCustomUserControlView : UserControl, IView
{
}

它只包含一个标签:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>

<asp:Label Text="Wow, what a view!" runat="server" />

1 个答案:

答案 0 :(得分:2)

能够通过使用用户控件作为资源调用Page.LoadControl来实现此功能。

Page.LoadControl(typeof(controls_controls_MyCustomUserControlView),null)不起作用,但是Page.LoadControl(“controls_MyCustomUserControlView.ascx”)会这样做。

由于控件位于外部程序集中,首先按照http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx

所述创建VirtualPathProvider和VirtualFile

自定义VirtualPathProvider将用于检查用户控件是否位于外部程序集中,VirtualFile(用户控件)将作为资源从程序集返回。

接下来设置Ninject模块以加载用户控件:

    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;
    }

“插件”只是用于在VirtualPathProvider中确定控件是否位于另一个程序集中的前缀。

如果您的用户控件具有命名空间,请确保在LoadControl中为控件名称添加前缀。另一件事是确保使用CodeBehind而不是CodeFile,因为ASP.NET将尝试加载CodeBehind文件。

<%@ Control Language="C#" AutoEventWireup="true" 
CodeBehind="~/MyCustomUserControlView.ascx.cs" Inherits="controls_MyCustomUserControlView" %>