静态/共享函数中的 LoadControl

发布于 2024-08-16 22:43:08 字数 1583 浏览 11 评论 0原文

有人知道如何在共享/静态函数内动态加载控件吗?该函数本身位于必须继承/抽象类的内部。 (这是一个 VB 中的 ASP.NET 项目)我想做这样的事情:
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

我的 C# 有点生疏,所以这可能有一些语法错误:(

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

其中 WidgetName 是一个枚举器。)

我收到“无法从共享方法或共享成员初始值设定项中引用类的实例成员,而无需使用类的显式实例。”,但我不明白这个错误。我明白这意味着什么,我只是不明白为什么编译器没有将调用 LoadControl 视为该类的显式实例。使用 LoadControl 从文件创建新控件有什么不明确的地方?我尝试创建一个新的用户控件并初始化它,然后使用 LoadControl 将其设置为不同的控件,但无济于事。我也不想进行 DirectCast,因为我试图将其放入共享的、mustinheret(抽象)类中,因此该类没有可在 <%@ Reference 中写入的 .aspx 文件Control="~/SomeControlPath.ascx" %>,所以类名不可用。

我想做的是编写一个静态函数,它接受一些值并仅根据该控件的源文件位置返回一个控件。最终结果是用户可修改的控件列表。他们获得一列控件,可以根据我指定的可用子控件的静态列表自由添加、删除或重新排序。我并不认同这种做法。它可能在很多方面都是错误的。

是的,我知道静态字符串存在代码味道,但实际上看起来并非如此;这是为了提出问题而进行的简化。

欢迎使用 C#、VB 或简单的英语解释。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

聚集的泪 2024-08-23 22:43:08

实际上,你可以这样做(它有效):

UserControl tmp0 = new UserControl();
Control ctl = tmp0.LoadControl("MyControl.ascx");

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

UserControl tmp0 = new UserControl();
Control ctl = tmp0.LoadControl("MyControl.ascx");
み格子的夏天 2024-08-23 22:43:08

LoadControlTemplateControl 类(Page 继承自该类)的实例方法,并且您没有 Page 的实例static 方法中的 类(没有 this 对象,因为它是静态方法)。

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).

物价感观 2024-08-23 22:43:08

这里有所有好的信息,但令我惊讶的是,没有人使用它来跳跃到原始问题的实际解决方案:

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

我测试了这个解决方案,它有效。

与 Rippo 的解决方案相比,我更喜欢它,因为它使调用者不必担心 LoadControl 详细信息。如果除了简单地返回结果控件之外还需要对结果控件执行更多工作,那么这绝对是一个更好的解决方案。

不过,如果没有 CSharpAtl 的回答,我就不会达到这个解决方案,因为我(愚蠢地)没有意识到 LoadControl 是 TemplateControl 上的一种方法。就像原来的海报一样,我对为什么会遇到同样的错误感到非常困惑。我不明白为什么不能在共享方法中加载控件,事实上,如果您知道如何在这种情况下调用 LoadControl 就可以了!

布莱恩

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

我一向站在原地 2024-08-23 22:43:08

是因为 LoadControl 无法从您的类中返回吗?您可以尝试这个吗...

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

并调用像 这样的方法,

... = LoadControl(GetWidget(name));

我怀疑另一种选择是强制转换控件

Control c;
...
Case ...
   c = (ControlName)LoadControl("~/Control1/.ascx");
   break;
...
return c;

但是调用代码仍然需要将其强制转换回其类型.. 。

Is it because LoadControl can't be returned from your class? Can you try this instead...

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

and call the method like

... = LoadControl(GetWidget(name));

I suspect that the other alternative is to cast the control

Control c;
...
Case ...
   c = (ControlName)LoadControl("~/Control1/.ascx");
   break;
...
return c;

However the calling code would still need to cast it back to its type...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文