Vb6 “Tag” property equivalent in ASP.Net?

后端 未结 8 1266
迷失自我
迷失自我 2021-01-12 11:19

I\'m looking for ideas and opinions here, not a \"real answer\", I guess...

Back in the old VB6 days, there was this property called \"Tag\" in all controls, that wa

相关标签:
8条回答
  • 2021-01-12 11:46

    You can also use the composite pattern instead of using 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;
    
    0 讨论(0)
  • 2021-01-12 11:46

    You can use asp:Hidden controls to store data between posts. Like will says, there's no sense to have a tag property if you lose it's value.

    0 讨论(0)
  • 2021-01-12 11:57

    You can add attributes to some controls, but that seems to add some nasty HTML around the rendered control, something like <div attrName="attrValue">... (it might be a span though)

    0 讨论(0)
  • 2021-01-12 11:59

    I took mdb's brilliant solution, and ported it over to C# for my own needs. I also changed the Tags from a Dictionary of String, String, to a Dictionary of String, Object... since theoretically any type of object can be stored in the Session, not just strings:

    using System.Collections.Generic;
    using System.Web;
    using System.Web.UI;
    
    public static class Extensions
    {
        public static void SetTag(this Control ctl, object tagValue)
        {
            if (ctl.SessionTagDictionary().ContainsKey(TagName(ctl)))
                ctl.SessionTagDictionary()[TagName(ctl)] = tagValue;
            else
                ctl.SessionTagDictionary().Add(TagName(ctl), tagValue);
        }
    
        public static object GetTag(this Control ctl)
        {
            if (ctl.SessionTagDictionary().ContainsKey(TagName(ctl)))
                return ctl.SessionTagDictionary()[TagName(ctl)];
            else
                return string.Empty;
        }
    
        private static string TagName(Control ctl)
        {
            return ctl.Page.ClientID + "." + ctl.ClientID;
        }
    
        private static Dictionary<string, object> SessionTagDictionary(this Control ctl)
        {
            Dictionary<string, object> SessionTagDictionary;
            if (HttpContext.Current.Session["TagDictionary"] == null)
            {
                SessionTagDictionary = new Dictionary<string, object>();
                HttpContext.Current.Session["TagDictionary"] = SessionTagDictionary;
            }
            else
                SessionTagDictionary = (Dictionary<string, object>)HttpContext.Current.Session["TagDictionary"];
            return SessionTagDictionary;
        }
    }
    
    0 讨论(0)
  • 2021-01-12 12:03

    I'm not sure what the tag property did in VB6, but maybe you're looking for the Attributes property of Web controls:

    MyImgCtrl.Attributes["myCustomTagAttribute"] = "myVal";
    
    0 讨论(0)
  • 2021-01-12 12:04

    No, there's no direct equivalent, but if you're using v3.5 of the Framework, you can add this functionality quite easily using an extension method. For example:

    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
    

    Then, in your ASP.NET pages, first bring your extensions into scope, e.g:

    Imports WebApplication1.Extensions
    

    ...and then use it your controls as desired:

    TextBox1.SetTag("Test")
    
    Label1.Text = TextBox1.GetTag
    

    LATER EDIT: and if you really, really don't want to store your tags in the Session object, it's possible to stuff them into your Viewstate instead. This will of course mean that your tags will be exposed in the page markup sent to the user (albeit in obfuscated form), and, unfortunately, that some reflection-fu is required, since the ViewState property of a Page is marked as 'protected' for some reason.

    So, this code should pretty much be considered for entertainment purposes only, unless you actually like to raise eyebrows during code reviews:

    <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
    

    FINAL EDIT (I promise...). And here's a way to get rid of the reflection: first, create a new class to expose the ViewState property with a usable protection level, then change your Code-Behind (.aspx.vb) classes to inherit that instead of Web.UI.Page, e.g.:

    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
    

    Now, in your extensions module, you can access this newly defined property as:

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

    Still a bit of a hack, but much more acceptable than using reflection...

    0 讨论(0)
提交回复
热议问题