2008-10-08 8 views
7

Estoy buscando ideas y opiniones aquí, no una "respuesta real", supongo ...Vb6 Propiedad "Tag" equivalente en ASP.Net?

Detrás en los viejos días VB6, había una propiedad llamada "Etiqueta" en todos los controles, eso era una forma útil de almacenar información personalizada relacionada con un control. Cada control único que tenía, y todo fue felicidad ...

Ahora, en .Net (al menos para WebForms), que ya no está allí ...

¿Alguien tiene un buen reemplazo para eso?

Encuentro este problema muy a menudo, donde tengo diferentes funciones que se ejecutan en diferentes momentos en el ciclo de vida, y hacen cosas con mis controles, y quiero mantenerlos separados como están, pero uno debe pasar información al otro sobre controles específicos.

Puedo pensar en un millón de alternativas (comenzando con un diccionario de nivel de módulo, obviamente), pero ninguna tan limpia como la buena etiqueta.

(NOTA: sé que puedo subclase todos los controles y usar mi versión en su lugar prefiero no.)

¿Alguna sugerencia? ¿Cómo resuelves esto normalmente? ¿Alguna idea sobre por qué eliminaron esto en primer lugar?

EDIT: Estoy buscando algo Intra-Request, no Inter-Request. No necesito esta información para seguir allí en un PostBack. Esto es entre los métodos _Load y _PreRender, por ejemplo.

EDIT2: SÉ que conozco mi ASp.Net y sé la diferencia entre el escritorio y la web, ¡muchachos !. Solo intento usar la abstracción que .Net me da al máximo. Entiendo las concesiones, créanme, y respondan asumiendo que sí.

Respuesta

4

No, no hay un equivalente directo, pero si está utilizando v3.5 del Framework, puede agregar esta funcionalidad bastante fácilmente usando un método de extensión. Por ejemplo:

Imports System.Runtime.CompilerServices 

Public Module Extensions 
    <Extension()> _ 
    Public Sub SetTag(ByVal ctl As Control, ByVal tagValue As String) 
    If SessionTagDictionary.ContainsKey(TagName(ctl)) Then 
     SessionTagDictionary(TagName(ctl)) = tagValue 
    Else 
     SessionTagDictionary.Add(TagName(ctl), tagValue) 
    End If 
    End Sub 

    <Extension()> _ 
    Public Function GetTag(ByVal ctl As Control) As String 
    If SessionTagDictionary.ContainsKey(TagName(ctl)) Then 
     Return SessionTagDictionary(TagName(ctl)) 
    Else 
     Return String.Empty 
    End If 
    End Function 

    Private Function TagName(ByVal ctl As Control) As String 
    Return ctl.Page.ClientID & "." & ctl.ClientID 
    End Function 

    Private Function SessionTagDictionary() As Dictionary(Of String, String) 
    If HttpContext.Current.Session("TagDictionary") Is Nothing Then 
     SessionTagDictionary = New Dictionary(Of String, String) 
     HttpContext.Current.Session("TagDictionary") = SessionTagDictionary 
    Else 
     SessionTagDictionary = DirectCast(HttpContext.Current.Session("TagDictionary"), _ 
      Dictionary(Of String, String)) 
    End If 
    End Function 
End Module 

Luego, en sus páginas ASP.NET, primero ponga sus extensiones dentro del alcance, e.g:

Imports WebApplication1.Extensions 

... y luego usarlo como sus controles deseada: editar

TextBox1.SetTag("Test") 

Label1.Text = TextBox1.GetTag 

después: y si realmente, realmente no desea almacenar sus etiquetas en el objeto Session, es posible rellenarlos en su Viewstate en su lugar. Esto significará, por supuesto, que sus etiquetas serán expuestas en el marcado de página enviado al usuario (aunque en forma ofuscada), y, desafortunadamente, que se requiere algún reflejo-fu, ya que la propiedad ViewState de una página está marcada como 'protegido' por alguna razón.

Por lo tanto, este código debe ser considerado más o menos para fines de entretenimiento, a menos que realmente como a levantar las cejas durante las revisiones de código:

<Extension()> _ 
    Public Sub SetTag(ByVal ctl As Control, ByVal tagValue As String) 
    ViewState.Add(ctl.ID & "_Tag", tagValue) 
    End Sub 

<Extension()> _ 
    Public Function GetTag(ByVal ctl As Control) As String 
    Return ViewState(ctl.ID & "_Tag") 
    End Function 

Private Function ViewState() As Web.UI.StateBag 
    Return HttpContext.Current.Handler.GetType.InvokeMember("ViewState", _ 
       Reflection.BindingFlags.GetProperty + _ 
       Reflection.BindingFlags.Instance + _ 
       Reflection.BindingFlags.NonPublic, _ 
       Nothing, HttpContext.Current.CurrentHandler, Nothing) 
End Function 

edición final (prometo ...). Y aquí hay una manera de deshacerse de la reflexión: primero, cree una nueva clase para exponer la propiedad ViewState con un nivel de protección utilizable, luego cambie sus clases de código subyacente (.aspx.vb) para heredar eso en lugar de Web.UI. página, por ejemplo:

Public Class PageEx 
    Inherits System.Web.UI.Page 

    Friend ReadOnly Property ViewStateEx() As Web.UI.StateBag 
    Get 
     Return MyBase.ViewState 
    End Get 
    End Property 
End Class 

Ahora, en su módulo de extensiones, se puede acceder a este inmueble recién definida como:

Private Function ViewState() As Web.UI.StateBag 
    Return DirectCast(HttpContext.Current.Handler, PageEx).ViewStateEx 
End Function 

Todavía un poco de un truco, pero mucho más aceptable que el uso de la reflexión ..

+0

Wow. Eso es MUY cercano a lo que estaba pidiendo y asumiendo que no había forma de hacerlo. No estoy muy contento con la sesión, pero definitivamente tendré que aprender esta cosa de Extensiones (estoy usando v2.0, pero AHORA voy a migrar :-D) –

+0

¡Eso es bastante astuto, en realidad! –

+0

¡Agradable! ¡Me encantaría darte más puntos por eso! Esperemos que implementen el karma por el que están hablando ... –

0

Puede agregar atributos a algunos controles, pero que parece añadir un poco de HTML desagradable alrededor del control prestado, algo así como <div attrName="attrValue"> ... (que podría ser un lapso sin embargo)

+0

Sí, no quiero la etiqueta de salir sin embargo. Es una cosa interna. Además, HTML no válido más adelante (no me importa ASP.Net lo hace todo el tiempo de todos modos, pero aún así) –

+0

¡Exactamente por qué no los uso! – harriyott

0

No estoy seguro de lo que el propiedad de etiqueta hizo en VB6, pero tal vez usted está en busca de la propiedad Attributes de controles web:

MyImgCtrl.Attributes["myCustomTagAttribute"] = "myVal"; 
+0

No. atributos de salida al HTML. Quiero algo interno. –

0

se preguntó acerca de ASP.Net, pero VB6 era un lenguaje de escritorio, y así eran los controles de tI de 'etiqueta'. El VBScript utilizado para el asp clásico no tenía realmente un concepto de control.

Ahora en .Net, para controles de escritorio puede usar herencia, que es mucho más poderosa que la antigua propiedad de Tag de todos modos. La herencia se aplica a los controles web también, aunque debe tener cuidado al usarla para mantener el estado.

+0

Sí, y luego tiene que SubClass cada control único que realice. No genial. Obtengo la diferencia entre la web y el escritorio, y ASP.Net es muy similar al escritorio, y SÍ tiene controles. Deberían haber agregado Tag allí. –

+0

No, solo tiene que subclasificar los controles donde desea usar la etiqueta. Probablemente deberías estar subclases más de todos modos. –

-1

Puede usar asp: controles ocultos para almacenar datos entre las publicaciones. Como dice will, no tiene sentido tener una propiedad de etiqueta si pierdes su valor.

+0

Ugh, incluso más feo. Y una vez más, podrían haberse serializado en Viewstate, sin necesidad de perderlo. Y HAY valor para mí, incluso si lo pierde. –

+0

Por favor, intente explicar mejor lo que quiere primero –

-1

La propiedad Tag siempre fue una especie de verruga Lo que fue útil como algo fuera de lo que podría colgar cualquier información que quisiera. Pero no estaba fuertemente tipado y realmente no lo hacía para un diseño coherente. La propiedad en sí misma colgaba del control como una extraña perilla. Lo mantuvieron en WinForms para facilitar el porteo del código desde VB6. La nueva clase WPF Control no tiene un Tag.

Con .NET tiene una orientación a objetos completa y un tipo de polimorfismo adecuado, por lo que puede escribir con fuerza cualquier información adicional que desee asociar con un código, ya sea en una subclase o Dictionary<Control,TValue>.

Si es en una sola petición Page y desea una solución general de un diccionario en la propia página para cada tipo de valor (por ejemplo, Dictionary<Control,string> y Dictionary<Control,BusinessObject>) debe ser exactamente lo que necesita.

+0

Claro. Pero eso es mucho más feo que la etiqueta, en serio. Obtengo todo lo que dices y acepto, pero fue muy útil. Está colocando los datos asociados justo donde debería estar, en lugar de estar en una variable "global" completamente fuera de la ruta. –

3

También puede utilizar el patrón compuesto en lugar de utilizar inheritence:

public class TaggedControl<TControl, TTag> : Control 
where TControl : Control, new() 
{ public TaggedControl() {this.Control= new TControl();} 

    public TControl Control {get; private set;} 
    public TTag  Tag  {get; set;}  

    protected override void CreateChildControls(){Controls.Add(Control);} 
} 

var textBox = new TaggedControl<TextBox, string>(); 
textBox.Tag = "Test"; 
label.Text = textBox.Tag;