使用LoadControl以编程方式加载用户控件(Type,Object())

Jak*_*ade 7 .net vb.net webusercontrol

我正在动态地向页面添加Web用户控件.使用LoadControl仅采用指向.ascx工作的虚拟路径的方法非常好.然而,过载LoadControl需要一个类型和一个参数数组引起了一些令人头疼的问题.

Web用户控件按预期实例化,但Web用户控件中包含的控件为null,一旦我尝试使用它们就会出现异常.很奇怪,因为它在使用第一版时起作用LoadControl.

Web用户控件,简单,带Literal控件:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="MyControl.ascx.vb" Inherits="MyControl" %>
<asp:Literal ID="myLiteral" runat="server"></asp:Literal>
Run Code Online (Sandbox Code Playgroud)

控件的代码背后:

Public Class MyControl
  Inherits System.Web.UI.UserControl

  Public Property Data As MyData  

  Public Sub New()

  End Sub

  Public Sub New(data As MyData)
    Me.Data = data
  End Sub

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    myLiteral.Text = Data.ID ' The Literal is null, but ONLY when I use the second LoadControl() method!
  End Sub

End Class
Run Code Online (Sandbox Code Playgroud)

以及.aspx我试图动态加载控件的相关代码:

Private Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
  Dim x = LoadControl(GetType(MyControl), New Object() {New MyData With {.ID = 117}})
  Page.Controls.Add(x)

  ' Using LoadControl("MyControl.ascx") works as expected!
End Sub
Run Code Online (Sandbox Code Playgroud)

Jak*_*ade 2

在 Steven Robbins这篇文章的帮助下,我最终得到了一个非常方便的扩展方法:

Imports System.Runtime.CompilerServices
Imports System.Web.UI
Imports System.Reflection

Module LoadControls
  <Extension()> _
  Public Function LoadControl(templateControl As TemplateControl, virtualPath As String, ParamArray constructorParams() As Object) As UserControl
    Dim control = TryCast(templateControl.LoadControl(virtualPath), UserControl)
    Dim paramTypes = constructorParams.Select(Function(p) p.GetType()).ToArray
    Dim constructor = control.GetType().BaseType.GetConstructor(paramTypes)

    If constructor Is Nothing Then ' Nothing if no such constructor was found.
      Throw New ArgumentException(String.Format("No constructor for control '{0}' with {1} parameter(s) were found.", virtualPath, paramTypes.Count))
    Else
      constructor.Invoke(control, constructorParams)
    End If

    Return control
  End Function

End Module
Run Code Online (Sandbox Code Playgroud)