Vb6 «Tag» свойство эквивалентно в ASP.Net? - PullRequest
7 голосов
/ 08 октября 2008

Я ищу идеи и мнения здесь, а не "реальный ответ", я думаю ...

В прежние времена VB6 во всех элементах управления существовало свойство Tag, которое было полезным способом хранения пользовательской информации, связанной с элементом управления. Каждый контроль имел его, и все было блаженством ...

Теперь в .Net (по крайней мере, для WebForms) его больше нет ...

У кого-нибудь есть хорошая замена для этого?

Я нахожу эту проблему очень часто, когда у меня разные функции, которые выполняются в разное время в жизненном цикле, и они делают что-то с моими элементами управления, и я хочу, чтобы они были такими же отдельными, как и они, но нужно передать информацию другой о конкретных элементах управления.

Я могу подумать о миллионе альтернатив (начиная со словаря на уровне модуля, очевидно), но ни одна из них не так чиста, как хороший старый тег.

(ПРИМЕЧАНИЕ. Я знаю, что могу создать подкласс для ВСЕХ элементов управления и использовать вместо него свою версию. Я бы не хотел)

Есть предложения? Как вы решаете это нормально? Любые идеи о том, почему они удалили это я в первую очередь?

РЕДАКТИРОВАТЬ: Я ищу что-то внутри запроса, а не между запросами. Мне не нужна эта информация, чтобы все еще быть там на PostBack. Например, это между методами _Load и _PreRender.

EDIT2: Я действительно знаю свой ASp.Net и знаю разницу между рабочим столом и сетью, ребята! Я просто пытаюсь использовать абстракцию, которую .Net дает мне по максимуму. Я понимаю компромиссы, поверьте мне, и, пожалуйста, ответьте, если я это сделаю.

Ответы [ 7 ]

4 голосов
/ 08 октября 2008

Нет, прямого эквивалента нет, но если вы используете v3.5 Framework, вы можете легко добавить эту функцию, используя метод расширения. Например:

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

Затем на своих страницах ASP.NET сначала перенесите ваши расширения в область действия, например:

Imports WebApplication1.Extensions

... и затем используйте его как хотите:

TextBox1.SetTag("Test")

Label1.Text = TextBox1.GetTag

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: и если вы действительно, действительно, не хотите хранить свои теги в объекте Session, вместо этого можно вставить их в Viewstate. Это, конечно, будет означать, что ваши теги будут отображаться в разметке страницы, отправленной пользователю (хотя и в запутанном виде), и, к сожалению, что требуется некоторое отражение-фу, так как свойство ViewState объекта По какой-то причине страница помечена как защищенная.

Таким образом, этот код должен рассматриваться только для развлекательных целей, если только вам не нравится , чтобы поднять брови во время проверки кода:

<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

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ (обещаю ...). И вот способ избавиться от отражения: сначала создайте новый класс, чтобы предоставить свойство ViewState с пригодным для использования уровнем защиты, затем измените классы Code-Behind (.aspx.vb), чтобы они наследовали его вместо Web.UI. Страница, например:

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

Теперь в вашем модуле расширений вы можете получить доступ к этому вновь определенному свойству как:

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

Все еще немного взломано, но гораздо более приемлемо, чем использование отражения ...

3 голосов
/ 08 октября 2008

Вы также можете использовать составной шаблон вместо наследования:

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 голосов
/ 08 октября 2008

Свойство Tag всегда было странной вещью, похожей на бородавку, и было полезным, как то, из чего можно было повесить любые данные, которые вы хотели. Но это не было строго напечатано, и это действительно не создавало последовательный дизайн. Само свойство просто зависало от контроля, как странная ручка. Они сохранили его в WinForms для облегчения переноса кода с VB6. Новый класс WPF Control не имеет Tag.

С .NET вы имеете полную объектную ориентацию и адекватный полиморфизм типов, так что вы можете строго набирать любую дополнительную информацию, которую хотите связать с кодом, будь то в подклассе или Dictionary<Control,TValue>.

Если это один запрос Page, и вы хотите общее решение, словарь на самой странице для каждого типа значения (например, Dictionary<Control,string> и Dictionary<Control,BusinessObject>) должен быть именно тем, что вам нужно.

0 голосов
/ 08 октября 2008

Вы можете использовать asp: Hidden для хранения данных между постами. Как говорит Воли, нет смысла иметь свойство тега, если вы потеряете его значение.

0 голосов
/ 08 октября 2008

Вы спрашивали о ASP.Net, но vb6 был языком рабочего стола, как и элементы управления с тегами. VBScript, используемый для классического asp, на самом деле не имел понятия управления.

Теперь в .Net для элементов управления рабочим столом вы можете использовать наследование, которое в любом случае намного мощнее, чем старое свойство Tag. Наследование применяется и к веб-элементам управления, хотя вы должны быть осторожны с его использованием для удержания состояния.

0 голосов
/ 08 октября 2008

Я не уверен, что свойство tag делало в VB6, но, возможно, вы ищете свойство Attributes веб-элементов управления:

MyImgCtrl.Attributes["myCustomTagAttribute"] = "myVal";
0 голосов
/ 08 октября 2008

Вы можете добавить атрибуты к некоторым элементам управления, но это, кажется, добавляет некоторый неприятный HTML вокруг визуализированного элемента управления, что-то вроде <div attrName="attrValue"> ... (хотя это может быть промежуток)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...