33377


ウィンドウズフォームのコントロールであるSystem.Windows.Forms.Controlには  
Tagプロパティというのがあり、好きなデータを突っ込んで便利に使えるようです。  
しかしASPのSystem.Web.UI.WebControls.WebControlにはTagプロパティはないようです。  
ASPでもTagを使いたいのですがどうすればよいでしょうか。

いまのところ解決策として各コントロールクラスを継承してTagプロパティを追加した  
新しいクラスを作って使っていますがもっと良い解決策はないでしょうか。

よろしくお願いします。


CC BY-SA 3.0
2017-03-17T00:56:34.093
33372
2017-03-17T05:03:09.787
2017-03-17T01:11:37.190
2238
18637
question
c# asp.net
C# System.Windows.Forms.Control.TagプロパティをASP.NETでも使いたい。


`WebControl`には拡張属性を設定する領域として[`Attributes`](https://msdn.microsoft.com/ja-
jp/library/system.web.ui.webcontrols.webcontrol.attributes\(v=vs.100\).aspx)プロパティが定義されています。

たとえば`data-tag`属性を使用する場合、`.aspx`側は以下のようになります。

[code]

    <form id="form1" runat="server">
    <div>
        <asp:Button runat="server" OnClick="Button_Click" data-tag="1" />
        <asp:Button runat="server" OnClick="Button_Click" data-tag="2" />
        <asp:Button runat="server" OnClick="Button_Click" data-tag="3" />
        <asp:Button runat="server" OnClick="Button_Click" data-tag="4" />
        <asp:Button runat="server" OnClick="Button_Click" data-tag="5" />
    </div>
    </form>
    
[/code]

コードビハインドでは`Attributes`のインデクサーから値が取得/設定できます。

[code]

    protected void Button_Click(object sender, EventArgs e)
    {
        var b = (Button)sender;
        var i = int.Parse(b.Attributes["data-tag"]);
        b.Attributes["data-tag"] = b.Text = (i * 2).ToString();
    }
    
[/code]

ただ本来はHTML属性を設定する場所ですので、副作用として出力結果に`data-
tag`属性が追加されることになります。もしユーザーに絶対知られたくない値を指定したいのであれば、セッションを利用すると複数同時リクエストの対応が難しいので`Page.ViewState`にJSONなどで保存しておくのが良いと思います。


CC BY-SA 3.0
2017-03-17T03:42:37.277
33377
2017-03-17T05:03:09.787
2017-03-17T05:03:09.787
5750
5750
33372
answer


まずWebFormsはブラウザーからのリクエストの度に毎回オブジェクトが生成し直されます。そのため、WinFormsのようにオブジェクトを維持することはできないため`Tag`プロパティが用意されていません。

ブラウザーからのリクエスト間で状態を保持する機能としていくつかの[サーバー側の状態管理オプション](https://msdn.microsoft.com/ja-
jp/library/z1hkazw7\(v=vs.100\).aspx#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E5%81%B4%E3%81%AE%E7%8A%B6%E6%85%8B%E7%AE%A1%E7%90%86%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3)が用意されています。無難なものとしては
**セッション状態** （session state）です。  
WebFormsからは`HttpContext.Current.Session`でアクセスできます。（[セッション状態から値を読み取る](https://msdn.microsoft.com/ja-
jp/library/03sekbw5\(v=vs.110\).aspx)、[セッション状態の値を保存する](https://msdn.microsoft.com/ja-
jp/library/6ad7zeeb\(v=vs.100\).aspx)）

> いまのところ解決策として各コントロールクラスを継承してTagプロパティを追加した  
>  新しいクラスを作って使っています

継承するくらいなら後付けで機能追加可能な拡張メソッドをお勧めします。`Tag`プロパティは作成できませんが、`GetTag()`拡張メソッドと`SetTag()`拡張メソッドを用意してはどうでしょうか？

[code]

    public static class TagExtensions {
        public static object GetTag(this Control self) {
            return HttpContext.Current.Session[self.UniqueID];
        }
        public static void SetTag(this Control self, object value) {
            HttpContext.Current.Session[self.UniqueID] = value;
        }
    }
    
[/code]

例として`UniqueID`プロパティを使用しましたが、適宜変更してください。


CC BY-SA 3.0
2017-03-17T04:16:36.940
33381
2017-03-17T04:16:36.940
4236
33372
answer