【问题标题】:ASP.Net c# - How do I instantiate an instance of a WebUserControl from within a App_Code class?ASP.Net c# - 如何从 App_Code 类中实例化 WebUserControl 的实例?
【发布时间】:2011-09-20 14:46:06
【问题描述】:

阿罗哈,

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

我阅读了here 以将 .cs 从控件移动到 App_Code 文件夹,但是当我这样做时,它不会编译,因为它看不到 ascx 中的控件有效。例如我得到CS0103: The name 'litTest' does not exist in the current context。因为它们是部分类,所以我在 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 类型:

Control c= Ctrl.LoadControl("~/Controls/CustomControlClass.ascx");

这样做可以让我将控件添加到页面并使其按预期工作。不利的一面是我无法访问任何控件属性。为了解决这个问题,我正在这样做:

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

这行得通,但我不确定它的使用成本有多高。我希望我可以直接施放控件,但尝试时出现错误。

我暂时不回答这个问题,看看是否还有其他选择。

【问题讨论】:

  • 您的页面是否正确放置在 default.aspx 页面上?

标签: c# asp.net webusercontrol


【解决方案1】:

使用

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 AutoComplete List 中看不到 ASP.customcontrolclass_ascx 类型,但编译时没有错误。

【讨论】:

  • 这更近了!我得到“无法将'ASP.customcontrolclass_ascx'类型的对象转换为'CustomControlClass'类型。”如果我使用 Control 作为它被添加到页面的类型,我会看到 TEST 这个词,但我无法设置 myValue。
  • 当我尝试使用 ASP.custoncontrolclass_ascx 时,我得到“CS0246:找不到类型或命名空间名称 'ASP'(您是否缺少 using 指令或程序集引用?)”不确定是什么参考我需要添加以使 ASP 命名空间正常工作。
  • 和你一样,我也收到了这条消息。但是忽略它,我尝试构建网站并成功编译。 (我使用 VS2008 和 .Net FrameWork 3.5 sp1)
【解决方案2】:

不确定您的代码发生了什么,但大部分使用您展示的内容对我有用:

~/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 对我有用。如果我理解正确,这就是问题所在?

【讨论】:

  • 是的,演员表对我不起作用我得到“无法将'ASP.customcontrolclass_ascx'类型的对象转换为'CustomControlClass'类型。”当我尝试时出错。我目前已经通过反思解决了这个问题,但完成这项工作似乎有点过头了。
  • 我在发布之前测试了上面的代码。它可以正常工作,包括演员表。你会试试吗?
【解决方案3】:

另一种有效的 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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 2016-11-16
    • 2023-03-19
    • 2023-03-30
    • 2020-10-13
    • 1970-01-01
    相关资源
    最近更新 更多