locked
Accessing a UserContol's custom properties in a regular class (not a page class) RRS feed

  • Question

  • User-1909413356 posted

     Hello,

     I have a class method which calls FindControl and creates a generic control reference as follows:

    Control oControl = oCriteriaTable.FindControl(sControlName);

    The generic oControl variable may end up containing a reference to a normal form control (e.g. Textbox, DropDownList) or it may end up with a reference to a UserContol (e.g. csiDateRange)

    For Textbox or DropDownList Controls I can access the generic control's properties by casting as follows:

    sControlValue = ((TextBox)oControl).Text;
    sControlValue = ((DropDownList)oControl).Text;

    The problem I am having is that I cannot figure out how to cast when a UserControl is in the generic so that I can get to it's custom properties.

    If this code is contained in an ASP page I can cast as follows:

    sControlValue = ((ASP.csiDateRange)oControl).SomeCustomProperty;

    However..... This code is contained in a regular class file not an ASP page. The (ASP.csiDateRange) cast fails to compile because the ASP namespace is unknown. How do I reference that namespace (and that of my UserControl)  in my class?

    I have the follow using directives for the class:

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    using System.Xml;
    using System.Collections;

    The UserControl Control Directive is as follows:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="csiDateRange.ascx.cs" Inherits="UserControls_csiDateRange" Classname="csiDateRange"%>

    Please note again that the (ASP.csiDateRange) works perfectly in an ASP page, Just not in a regular class definition.

    Any ideas????

    Thanks,

     Tony

    Friday, October 13, 2006 4:29 PM

Answers

  • User722206734 posted

    Ok, this seems far too easy for how this thread is ending up.  Have you tried:

    myUserControl uc = this.Page.FindControl("<UserControl ID>");

    If there is a proprty called MyText then you would only need to say:

    uc.MyText = "My New Text!";

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 13, 2007 1:52 PM

All replies

  • User2032526919 posted

    Hi,

    your user control would need to have a base class, specified on same place where this class so that it could reference the user control with the base type. See Rick Strahl's excellent post about the subject: http://west-wind.com/weblog/posts/3016.aspx

    Saturday, October 14, 2006 9:18 AM
  • User-1909413356 posted

    Joteke, 

    I really apprecaite your reply as almost none of my posts here are ever responded to. Unfortunately, I don't understand your suggestion. My user control does have a base class: System.Web.UI.UserControl.  The article you referred to is a good one but I don't understand how it answers this issue. As a metter of fact the author states:

    "For normal application usage this is not a big issue as in most applications developers will drop controls onto a Page visually. However, for dynamically loaded user controls things are going to be tricky – I don’t see how you can truly dynamically load a user control any more assuming you can’t add the <@ Register > directive to the page explictly. Maybe there’s some way to do the equivalent of <@ Register > in code? If there is, I couldn’t find it…"

    The problem he states is nearly identical to my issue in that this is a class, not a page, so there is no where to add a <@ Register> or <@ Reference > directive so that I can access the properties of the UserControl.  Could you provide a short example of the approach you are suggesting?

    Meanwhile I have come to a less than ideal workaround using reflection. Below is an example for others who may be wrestling with this issue:

    ...

    ...

    using System.Reflection;

    ...

    static public class MyTestClass {

     // This WON'T work because namespace ASP is unknown in a regular class
     /*
     static public String GetAPropertyValueViaReflection() {
      Control oControl = oSomeContainer.FindControl("myKnownUserControl");
      sControlValue = ((ASP.myKnownUserControl)oControl).SomeKNownProperty;
      return sControlValue;
     }
     */

     // This DOES work until I can figure out how to get a true reference to "myKnownUserControl" 
     static public String GetAPropertyValueViaReflection() {
      Control oControl = oSomeContainer.FindControl("myKnownUserControl");
      PropertyInfo pi = oControl.GetType().GetProperty("SomeKNownProperty");
      sControlValue = pi.GetValue(oControl, null).ToString();
                           
      return sControlValue;
     }
    }

    Saturday, October 14, 2006 1:44 PM
  • User2032526919 posted

    Exaclty, your control has that as base class when you could basically in the code use only that type to refer to the UC. However, if you write your own class (in the same library where you try to reference it), which derives from System.Web.UI.UserControl

    public class MyClass : System.Web.UI.UserControl
    {

    }

    and specify all the members etc here (you'd also need to use CodeFileBaseClass attribute in case they are control members). Essentially mechanism Rick has described like this

    This is a pretty major change in the way ASP.NET works. There’s a workaround for this, but it’s not pretty:

     

    • Create a base class for your page and make it inherit from Page
    • Store this Page either in APP_CODE or in a separate assembly so it’s visible to your pages
    • Implement your Public interface on this base Page
    • Then create your Page and make it inherit from this base Page
    • Now when you need to cast, cast to the base type

     

    BTW: I've commented on that post about the @Register

    re: Understanding Page Inheritance in ASP.NET 2.0 tammi 12, 2006 04:51 Teemu Keiski

    Equivalent of using @register in code is running the same through Page.ParseControl. Ugly as hell but seems to work,


    Dim c As Control = Page.ParseControl("<%@Register TagPrefix=""rc"" TagName=""c"" Src=""subfolder/uc_subfolder.ascx""%><rc:c runat='server' />")
    form1.Controls.Add(c)

     

     

    Tuesday, October 17, 2006 5:57 AM
  • User1671382754 posted

    I think this is what you're trying to accomplish. Substitute Me.Page for your control and you should be on your way. 

     

    'Get the year from the page property

    Dim propInfo As System.Reflection.PropertyInfo = Me.Page.GetType.GetProperty("SomePropName")

    Dim prop As Object = propInfo.GetValue(Me.Page, Nothing)

    Wednesday, June 13, 2007 1:17 PM
  • User722206734 posted

    Ok, this seems far too easy for how this thread is ending up.  Have you tried:

    myUserControl uc = this.Page.FindControl("<UserControl ID>");

    If there is a proprty called MyText then you would only need to say:

    uc.MyText = "My New Text!";

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, June 13, 2007 1:52 PM
  • User722206734 posted

    Ok, this seems far too easy for how this thread is ending up.  Have you tried:

    myUserControl uc = this.Page.FindControl("<UserControl ID>");

    If there is a proprty called MyText then you would only need to say:

    uc.MyText = "My New Text!";

    Wednesday, June 13, 2007 1:53 PM
  • User509133639 posted

    this does not work.  what if i am inside a class (say, MyClass.vb) and have a method that passes a page variable to it.  I want to add a control (say, MyControl.ascx) to that page dynamically, but I can't simply go

    dim ctl as MyControl = CType(page.LoadControl("MyControl.ascx"), MyControl)

    MyControl isn't recognized as a type, and so far as I've seen, there's no workaround for this.  Why did ASP.NET stop supporting user controls as objects? Seems stupid to me.

    Friday, January 4, 2008 3:31 PM
  • User2032526919 posted

    It did not, but provided two models for working with it. The model which doesn't recognice types without having a base class or @reference directive, a web site project, does so to avoid explicit compilation step when making changes during development. And since there isn't that step, the type cannot be implicitly known as it's not compiled beforehand into an assembly, but you must tell what it is. Other reason is that App_Code is compiled before user controls or pages.

    When using Page.LoadControl you get back  a control instance but the compiler hasn't been told what MyControl type is. And it can only be told by having

    <%@ Reference Control="MyControl.ascx" %>

    And if you need that type in a class, you need to declare the base type in App_Code or external control project/class library.

    The other model, Web Application Project also called WAP, which works similarly to the model in VS2003, has explicit compilation step, and therefore the type of the user control is known available on the entire project. 

    Sunday, January 6, 2008 4:11 AM
  • User830714299 posted

     Using the above example:

    dim ctl as MyControl = CType(page.LoadControl("MyControl.ascx"), MyControl)

    You can change it to:

    dim ctl as Object = CType(page.LoadControl("MyControl.ascx"), Object)

    This effectively abstracts the control to a level where you can make use of the fact that the Object class allows you to reference any property at design time. (ie, Late binding)

    ctl.Lala will compile happily, but will fail at runtime if no "Lala" property exists.  If the "Lala" property does exist at runtime, then you're in business. 

    I just applied this technique to an instance where I had a class in app_code that needed to reference a usercontrol on several pages.

     

     

     

     

    Wednesday, August 12, 2009 4:34 PM