Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LoadControl in static/shared function

Anyone know how I can dynamically load a control inside of a shared/static function? The function itself is inside of a mustinherit/abstract class. (It's an ASP.NET project in VB) I want to do something like this:
VB:

    Public Shared Function GetWidget(ByVal name As WidgetName) As Control
        Select Case name
            Case WidgetName.Name1
                Return LoadControl("~/Control1.ascx")
            Case WidgetName.Name2
                Return LoadControl("~/Control2.ascx")
            Case WidgetName.Name3
                Return LoadControl("~/Control3.ascx")
        End Select
    End Function

my C# is a little rusty, so this might have some syntax errors:

Public Static Control GetWidget(WidgetName name)  
{  
    switch (name)  
    {  
        Case WidgetName.Name1:  
            return LoadControl("~/Control1.ascx");  
            break;  
        Case WidgetName.Name2:  
            return LoadControl("~/Control2.ascx");  
            break;  
        Case WidgetName.Name3:  
            return LoadControl("~/Control3.ascx");  
            break;  
    }  
}  

(Where WidgetName is an enumerator.)

I'm getting "Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.", but I don't understand this error. I understand what it means, I just don't understand why calling LoadControl isn't seen by the compiler as being an explicit instance of the class. What's not explicit about using LoadControl to create a new control from a file? I tried creating a new user control and initializing it, then setting it to a different control with LoadControl to no avail. I also don't want to do a DirectCast because I'm trying to put this in a shared, mustinheret (abstract) class, which therefore doesn't have an .aspx file to write in a <%@ Reference Control="~/SomeControlPath.ascx" %>, so the class name is unavailable.

What I'm trying to do is write a static function that takes some value and returns a control based only on that control's source file location. The end result is a user-modifiable list of controls. They get a column of controls that they freely add, remove, or reorder based on a static list of available child controls that I specify. I'm not married to this approach; it might be really wrong in more ways than one.

yeah, I know the static strings being there is code smell, it doesn't actually look like that; it's a simplification for the sake of asking the question.

C#, VB, or plain English explanations all welcome.

like image 388
jorelli Avatar asked Dec 30 '09 17:12

jorelli


3 Answers

Actually, you can do it like this (it works):

UserControl tmp0 = new UserControl();
Control ctl = tmp0.LoadControl("MyControl.ascx");
like image 149
Gallegher Avatar answered Nov 18 '22 20:11

Gallegher


LoadControl is an instance method on the TemplateControl class which the Page class inherits from, and you do not have an instance of the Page class inside your static method (there is no this object because it is a static method).

like image 23
CSharpAtl Avatar answered Nov 18 '22 18:11

CSharpAtl


All good information here, but I'm surprised that no one has used it to make the leap to an actual solution to the original question:

Public Shared Function GetWidget(ByVal name As WidgetName,
                                 ByVal onTemplate As TemplateControl) As Control
    Select Case name
        Case WidgetName.Name1
            Return onTemplate.LoadControl("~/Control1.ascx")
        Case WidgetName.Name2
            Return onTemplate.LoadControl("~/Control2.ascx")
        Case WidgetName.Name3
            Return onTemplate.LoadControl("~/Control3.ascx")
    End Select
End Function

I tested this solution and it woks.

I like it better than Rippo's solution because it prevents the caller from having to worry about the LoadControl details. And this is definitely a better solution if there is more work to be done to the resulting control other than simply returning it.

I would not have reached this solution without CSharpAtl's answer, though, because I (stupidly) did not realize that LoadControl is a method on TemplateControl. Like the original poster, I was very confused about why I was getting the same error. I could not understand why it would not be OK to load a control in a shared method, and in fact, it is OK if you know how to call LoadControl in this context!

Brian

like image 37
BrianFinkel Avatar answered Nov 18 '22 20:11

BrianFinkel