开发者

ASP.Net c# - How do I instantiate an instance of a WebUserControl from within a App_Code class?

Aloha,

I have a custom control that I need to instantiate from within a class and add to a page. My class has a function that I pass the Page to so i have access to the controls on the page. I'm using this method to add standard ASP controls already and everything it working as expected. My problem is that the type for the custom control is know defined?

I read here to move the .cs from the control into the App_Code folder but when I do that it won't compile as it doesn't see the controls in the ascx as valid. For example I get CS0103: The name 'litTest' does not exist in the current context. So as they are partial classes I created a new empty partial class in the App_Code folder and left the control's .cs file alone.

Well it compiles this way but when I add the control to the Page.controls collection, I dont see anything on the page where it should be. For example I added TEST to the bottom of the ascx file, it I dont see it on the page. Additionally the control has variables that I need to set that I don't have access to when using the empty partial class.

I know that what I am trying to do works with standard controls, why can't I seem to make this work with a custom control?

My partial class in the App_Code folder:

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

}

My partial class in for the user control:

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

My user control ascx:

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

My App_Code class:

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

The page output does not have the word TEST on it at all. The word HELLO shows up just fine. I've tried calling the MyClass.doWork() from the pages Load, Init and PreInit callbacks, all result in the dame thing.

Update:

As Minh Nguyen suggested I can use Ctrl.LoadControl("~/Controls/CustomControlClass.ascx"); to load the control but I can not cast it as its own type I have to assign it as a Control type:

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

Doing this will let me add the control to the page and have it work as expected. The down side is that I have no access to any of the controls properties. To solve this i am doing this:

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

This works, but I'm not sure how expensive that it to use. I wish I could just cast the control but I get an error when I try.

I'm leaving this unanswered for a bit to see if there are any other options.


Use

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

instead of

CustomControlClass c = new CustomControlClass();

UPDATE: fix cast bug

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

you can't see ASP.customcontrolclass_ascx type in VS AutoComplete List but it compiled with no error.


not sure what's going on with your code, but using mostly what you showed works for me:

~/controls/testControl.ascx:

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

.aspx page:

<%@ 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);
  }
}

in other words the cast to CustomControlClass when calling LoadControl() works for me. if i understood you correctly that's the problem?


A different way of LoadControl which works (only .NET 4 tested)

Usage is as follows in any page you can call

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜