2009-12-30 16 views
5

Alguien sabe cómo puedo cargar dinámicamente un control en el interior de una función compartida/estática? La función en sí está dentro de una clase mustinherit/abstract. (Es un proyecto ASP.NET en VB) Quiero hacer algo como esto:
VB:LoadControl en función estática/compartida

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 

mi C# es un poco oxidado, por lo que este podría tener algunos errores de sintaxis:

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

(Donde WidgetName es un enumerador)

Me aparece "No puedo hacer referencia a un miembro de instancia de una clase desde un método compartido o inicializador de miembro compartido sin una instancia explícita de la clase.", Pero no lo hago entiendo este error Entiendo lo que significa, simplemente no entiendo por qué llamar al LoadControl no es visto por el compilador como una instancia explícita de la clase. ¿Qué no es explícito sobre el uso de LoadControl para crear un nuevo control desde un archivo? Traté de crear un nuevo control de usuario e inicializarlo, y luego establecerlo en un control diferente con LoadControl en vano. Tampoco quiero hacer un DirectCast porque estoy tratando de poner esto en una clase compartida, mustinhere (abstracta), que por lo tanto no tiene un archivo .aspx para escribir en un <%@ Reference Control="~/SomeControlPath.ascx" %>, por lo que el nombre de la clase no está disponible .

Lo que estoy tratando de hacer es escribir una función estática que tiene algún valor y devuelve un control basado únicamente en la ubicación del archivo fuente de ese control. El resultado final es una lista de controles modificables por el usuario. Obtienen una columna de controles que agregan, eliminan o reordenan libremente en función de una lista estática de controles secundarios disponibles que especifico. No estoy casado con este enfoque; podría estar realmente mal en más de un sentido.

Sí, lo sé las cuerdas estáticas estar allí es el olor de código, que en realidad no se parecen a eso; es una simplificación por el hecho de hacer la pregunta.

C#, VB, o explicaciones en inglés llano todos bienvenidos.

Respuesta

0

¿Es porque LoadControl no puede ser devuelto a su clase? Se puede probar este lugar ...

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

y llamar al método de

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

Sospecho que la otra alternativa es echar el control

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

Sin embargo, el código de llamada seguiría siendo necesario para lanzarlo de nuevo a su tipo ...

+0

No se trata de lo que está siendo devuelto ... es que no se puede llamar al método LoadControl desde el interior el método estático ... porque no hay instancia. – CSharpAtl

+0

¡Sin preocupaciones, estado allí! Tómate un café y aléjate de la cerveza :) :) – Rippo

+0

@CSharpAtl - Estás en lo cierto y por eso te sugerí una alternativa. – Rippo

1

LoadControl es un método de instancia de la clase TemplateControl el que la clase hereda de Page, y usted no tiene una instancia de la clase Page dentro de su método static (no hay this objeto porque se trata de un método estático).

+0

ah, gracias por los datos técnicos , eso es útil para saber Comprendo el error ahora. Hasta ahora no había pensado mucho sobre el contexto de la definición de LoadControl, simplemente lo daba por hecho y lo usé. – jorelli

+0

En su menú intellisense ... 'LoadControl' no debería haber surgido como una opción en su método estático. – CSharpAtl

+0

sí, no es así. Escribí el cuerpo del método con la firma que lo especificaba como un método de instancia, luego decidí que sería una lectura más fácil si se compartía, así que cambié la firma, que es cuando comencé a ver el error y no entendía del todo. eso. – jorelli

0

Toda buena información aquí, pero me sorprende que nadie lo ha utilizado para dar el salto a una solución real a la pregunta original:

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 

He probado esta solución y woks.

Me gusta más que la solución de Rippo porque evita que la persona que llama tenga que preocuparse por los detalles de LoadControl. Y esta es definitivamente una mejor solución si hay más trabajo por hacer para el control resultante que simplemente devolverlo.

No habría llegado a esta solución sin la respuesta de CSharpAtl, porque (estúpidamente) no me di cuenta de que LoadControl es un método en TemplateControl. Al igual que el póster original, estaba muy confundido acerca de por qué estaba obteniendo el mismo error. No podía entender por qué no estaría bien cargar un control en un método compartido, y de hecho, ¡está bien si sabes cómo llamar a LoadControl en este contexto!

Brian

10

En realidad, puede hacerlo de esta manera (que funciona):

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