ASP.Net c# - 如何在 App_Code 类中实例化 WebUserControl 的实例?

3

你好,

我有一个自定义控件需要在类内实例化并添加到页面中。我的类有一个函数,我将Page传递给它,以便可以访问页面上的控件。我已经使用这种方法添加了标准ASP控件,一切都按预期工作。我的问题是自定义控件的类型未定义?

我在这里读到,将.cs文件从控件移动到App_Code文件夹中,但当我这样做时,它无法编译,因为它无法将ascx中的控件视为有效控件。例如,我会得到CS0103:当前上下文中不存在名称“litTest”。因此,由于它们是部分类,我在App_Code文件夹中创建了一个新的空部分类,并保留了控件的.cs文件。

这样编译就可以了,但是当我将控件添加到Page.controls集合中时,在应该出现的位置上看不到任何东西。例如,我在ascx文件底部添加了TEST,但在页面上看不到它。此外,控件具有我需要设置的变量,但在使用空部分类时我无法访问它们。

我知道我尝试做的事情对于标准控件是有效的,为什么我似乎无法使自定义控件起作用呢?

我在App_Code文件夹中的部分类:

public partial class CustomControlClass : System.Web.UI.UserControl
{

}

我的部分类是为用户控件而设计的:

public partial class CustomControlClass : System.Web.UI.UserControl
{
    private int _myValue= -1;
    public int myValue
    {
        get { return _myValue; }
        set { _myValue= value; }
    }
    protected void Page_Init(object sender, EventArgs e)
    {
        litTest.Text = "TEST";
    }
}

我的用户控件ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CustomControlClass.ascx.cs" Inherits="CustomControlClass" %>
<asp:Literal ID="litTest" runat="server"></asp:Literal>
TEST

我的 App_Code 类:

public class MyClass
{
    public static void doWork(Page Ctrl)
    {
        CustomControlClass c = new CustomControlClass();
        //c.myValue = 1;  // Wont compile with this line
        Ctrl.Controls.Add(c);

        Literal l = new Literal();
        l.Text = "HELLO";
        Ctrl.Controls.Add(l);
    }
}

页面输出中根本没有单词“TEST”。单词“HELLO”显示得很好。我已经尝试从页面的LoadInitPreInit回调中调用MyClass.doWork(),但结果都是一样的。
更新:
正如Minh Nguyen建议的那样,我可以使用Ctrl.LoadControl("~/Controls/CustomControlClass.ascx");来加载控件,但我不能将其强制转换为自己的类型,我必须将其分配为控件类型:
Control c= Ctrl.LoadControl("~/Controls/CustomControlClass.ascx");

这样做可以让我将控件添加到页面并按预期工作。缺点是我无法访问任何控件属性。为解决此问题,我正在执行以下操作:

c.GetType().GetProperty("myValue").SetValue(c, 1, null);

这个方法可以运行,但我不确定使用它会不会很昂贵。我希望可以直接转换控件,但是尝试时出现了错误。
我暂时不回答这个问题,想看看是否有其他的选项。

你的页面是否正确放置在 default.aspx 页面上? - safi
3个回答

4
使用
CustomControlClass c = (CustomControlClass)Ctrl.LoadControl("~/VirtualPathToASCX/CustomControlClass.ascx");

替代

CustomControlClass c = new CustomControlClass();

更新:修复类型转换错误

//LoadControl
ASP.customcontrolclass_ascx c = (ASP.customcontrolclass_ascx)this.LoadControl("~/Controls/CustomControlClass.ascx");
//set myValue
c.myValue = 3;

在VS的自动完成列表中,您无法看到ASP.customcontrolclass_ascx类型,但它可以编译而无错误。


这更接近了!我得到了“无法将类型为'ASP.customcontrolclass_ascx'的对象转换为类型'CustomControlClass'。”如果我使用Control作为类型,它会被添加到页面上,我可以看到单词TEST,但我无法设置myValue。 - Justin808
2
当我尝试使用ASP.custoncontrolclass_ascx时,会出现“CS0246:找不到类型或命名空间名称'ASP'(是否缺少using指令或程序集引用?)”的错误。不确定需要添加哪个引用才能使ASP命名空间正常工作。 - Justin808
我也收到了同样的消息,但是请忽略它。我尝试构建网站,编译成功了。(我使用带有 .Net Framework 3.5 sp1 的 VS2008) - Minh Nguyen

1

不确定你的代码出了什么问题,但是使用你展示的大部分代码对我来说是有效的:

~/controls/testControl.ascx:

<%@ Control Language='C#' AutoEventWireup='false' 
  Inherits='CustomControlClass' 
%>
<asp:Literal ID='litTest' runat='server'></asp:Literal>

.aspx页面

<%@ Page Language='C#' %>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<script runat='server'>
protected override void OnInit(EventArgs e) {
  base.OnInit(e);
  MyClass.doWork(this.Page);
}
</script>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head runat='server'><title></title></head>
<body><form id='form1' runat='server'>
</form></body></html>

~/app_code/CustomControlClass.cs:

using System;
using System.Web;
using System.Web.UI.WebControls;

public partial class CustomControlClass : System.Web.UI.UserControl {
  private int _myValue= -1;
  public int myValue {
    get { return _myValue; }
    set { _myValue= value; }
  }
  private Literal _litTest;
  public Literal litTest {
    get { return _litTest; }
    set { _litTest= value; }

  }
  protected override void  OnInit(EventArgs e) {
    base.OnInit(e);
    litTest.Text = "TEST";
  }
}

~/app_code/MyClass:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public class MyClass {
  public static void doWork(Page Ctrl) {
    CustomControlClass c = 
      (CustomControlClass) Ctrl.LoadControl("~/controls/testControl.ascx");
    c.myValue = 1;
    Ctrl.Form.Controls.Add(c);

    Literal l = new Literal();
    l.Text = string.Format(
      "<p>CustomControlClass.myValue: {0} </p>", 
      c.myValue
    )
    + string.Format(
      "<p>CustomControlClass.litTest.Text: {0} </p>", 
      c.litTest.Text
    )
    ;
    Ctrl.Form.Controls.Add(l);
  }
}

换句话说,在调用LoadControl()时,将类型转换为CustomControlClass对我有用。如果我理解正确,这就是问题所在?


1
是的,强制类型转换对我不起作用。当我尝试时,会出现“无法将类型为'ASP.customcontrolclass_ascx'的对象强制转换为类型'CustomControlClass'。”错误。目前我已经通过反射解决了这个问题,但这似乎有些过度,只是为了完成工作。 - Justin808
我在发布之前测试了上面的代码,它可以正常工作,包括强制转换。你能试试吗? - kuujinbo

1

一种不同的LoadControl方法,已经测试过(仅适用于.NET 4)

在任何页面中,您可以按以下方式使用:

protected void Page_Load(object sender, EventArgs e)
{
    Control ctrl = SomeClass.GetNewUserControl( "hello add me");

    Panel1.Controls.Add(ctrl);
}

~/app_code/BaseMyControls.cs:

using System;
using System.Collections.Generic;
using System.Web;

/// <summary>
/// Summary description for BaseMyControls
/// </summary>
public class BaseMyControls  : System.Web.UI.UserControl
{
    public string strProperty;

    public BaseMyControls()
    {

    }
}

~/app_code/SomeClassInApp_Code.cs:

using System;
using System.Collections.Generic;
using System.Web;

/// <summary>
/// Summary description for SomeClassInApp_Code
/// </summary>
public class SomeClassInApp_Code
{
    public static System.Web.UI.Control GetNewUserControl(string someString)
    {
        BaseMyControls bc = (BaseMyControls)(new System.Web.UI.UserControl()).LoadControl("~/controls/MyUC.ascx");
        bc.strProperty = someString;
        return bc;
    }
}

~/controls/MyUC.aspx:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyUC.ascx.cs" Inherits="MyUC" %>
<asp:Label runat="server" ID="lbl" /></asp:Label>

~/controls/MyUC.aspx.cs:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class MyUC : BaseMyControls
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string a = this.strProperty;

        lbl.Text = a;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接