7

「本当の答え」ではなく、ここでアイデアや意見を探していると思います...

古い VB6 の時代には、すべてのコントロールに「タグ」と呼ばれるこのプロパティがあり、コントロールに関連するカスタム情報を保存するのに便利な方法でした。すべてのコントロールにそれがあり、すべてが至福でした...

現在、.Net (少なくとも WebForms の場合) では、もう存在しません...

誰かがそれに代わる良いものを持っていますか?

私はこの問題を非常に頻繁に見つけます。ライフサイクルのさまざまな時期に実行されるさまざまな機能があり、それらは私のコントロールで処理を行います。それらをそのまま別々に保ちたいのですが、一方が他方に情報を渡す必要があります。特定のコントロール。

100 万通りの代替案を思いつくことができますが (明らかにモジュール レベルの辞書から始めます)、古き良き Tag ほどクリーンなものはありません。

(注:すべてのコントロールをサブクラス化し、代わりに自分のバージョンを使用できることはわかっています。むしろそうはしません)

助言がありますか?これをどうやって解決するのが普通ですか?そもそもなぜ彼らがこれを削除したのかについてのアイデアはありますか?

編集:リクエスト間ではなく、リクエスト内のものを探しています。この情報が PostBack に残っている必要はありません。これは、たとえば、_Load メソッドと _PreRender メソッドの間です。

EDIT2: 私は自分の ASP.Net を知っていますし、デスクトップと Web の違いも知っています。私は、.Net が提供する抽象化を最大限に活用しようとしています。私はトレードオフを理解しています。私を信じてください。私が理解していると仮定して答えてください。

4

8 に答える 8

5

いいえ、直接同等のものはありませんが、フレームワークの v3.5 を使用している場合は、拡張メソッドを使用してこの機能を非常に簡単に追加できます。例えば:

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

LATER EDIT:そして、本当にタグをSessionオブジェクトに保存したくない場合は、代わりにそれらをViewstateに詰め込むことができます。これはもちろん、ユーザーに送信されるページ マークアップでタグ公開されることを意味し (難読化された形式ではありますが)、残念ながら、Page の 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 プロパティを公開する新しいクラスを作成してから、コード ビハインド (.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

まだ少しハックですが、リフレクションを使用するよりもはるかに受け入れられます...

于 2008-10-08T15:03:00.047 に答える
3

継承を使用する代わりに、複合パターンを使用することもできます。

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;
于 2008-10-08T16:41:59.193 に答える
0

Attributesタグ プロパティが VB6 で何をしていたかはわかりませんが、Web コントロールのプロパティを探しているのかもしれません。

MyImgCtrl.Attributes["myCustomTagAttribute"] = "myVal";
于 2008-10-08T14:43:03.160 に答える
0

ASP.Net について質問されましたが、vb6 はデスクトップ言語であり、「タグ付き」コントロールでもありました。従来の ASP で使用される VBScript には、実際にはコントロールの概念がありませんでした。

.Net では、デスクトップ コントロールに継承を使用できます。これは、古い Tag プロパティよりもはるかに強力です。継承は Web コントロールにも適用されますが、状態を保持するために使用する場合は注意が必要です。

于 2008-10-08T14:43:47.760 に答える
0

一部のコントロールに属性を追加することはできますが、レンダリングされたコントロールの周りに厄介な HTML を追加しているように見えます<div attrName="attrValue">

于 2008-10-08T14:41:50.200 に答える
-1

asp:Hidden コントロールを使用して、投稿間でデータを保存できます。will が言うように、値を失った場合、タグ プロパティを持つ意味はありません。

于 2008-10-08T14:45:27.447 に答える
-1

Tagプロパティは常に、必要なデータをぶら下げることができる何かとして役立つ、奇妙なイボのようなものでしたしかし、それは強く型付けされたものではなく、首尾一貫した設計にはなりませんでした。プロパティ自体は、奇妙なノブのようにコントロールからぶら下がっていました。VB6 からのコードの移植を容易にするために、WinForms に保存しました。新しい WPFControlクラスにはTag.

.NET を使用すると、完全なオブジェクト指向と適切な型ポリモーフィズムが得られるため、コードに関連付ける必要のある追加情報を、サブクラスであろうとDictionary<Control,TValue>.

それが単一のPageリクエスト内にあり、一般的な解決策が必要な場合は、各値タイプ(Dictionary<Control,string>およびなどDictionary<Control,BusinessObject>)のページ自体のディクショナリがまさに必要なものである必要があります。

于 2008-10-08T15:06:04.907 に答える