トップ回答者
ViewStateのラッパークラス作成について

質問
-
ViewStateのラッパークラスを作成したいのですが、どう記述したら良いか悩んでおります。
Sessionだと下記の感じなのですが、ViewStateの場合はどうしたら良いのでしょうか。
ご教示願います。
public class DataSession
{public Object this[String strValue]
{
get {return HttpContext.Current.Session[strValue];}
set {HttpContext.Current.Session[strValue] = value;}
}
public Object this[Int intValue]
{
get {return HttpContext.Current.Session[intValue];}
set {HttpContext.Current.Session[intValue] = value;}
}}
回答
-
そこで、恐縮なのですが、技術的に可能なのかどうかをご教示頂けますか。
後学の為に知りたいと考えています。あ、すみません。質問に全く答えていない事に今気付きました。質問に答えていないのにグダグダ言ってもしょうがありませんよね。
Session のようにはいきません。
Page.Session は単に HttpContext.Current.Session を参照しているだけですが、
先述したように ViewState はあくまで Page のデータです。
さらに、ViewState は protected なので以下のようにもできません。Code Snippetpublic class DataViewState{
private Page _page;public DateViewState(Page page){
_page = page;
}public string Hoge{
get{ return (string)_page.ViewState["Hoge"]; }
}
}という事で無理です。
-
marumusisan さんからの引用 public Object this[String strKey]
{
get
{
object o = ViewState[strKey];
return (o == null)? String.Empty : (string)o;}
set
{
ViewState[strKey] = value;
}
}たとえコンパイル通っても無意味だと思います。ラップになっていません。
#インデクサでしたか…プロパティにするのかと思ってました。
プロパティにするなら先ほど書いた
StateBag クラス
http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx
のサンプルのようにするのではダメでしょうか。
ViewState はページ固有のデータなので、他からアクセスすることは考えられないので、やはり囚人様が仰せになるとおり、Session プロパティや ViewState プロパティに直接アクセスするのがいいと思います。
方法 : ビューステートから値を読み取る
http://msdn2.microsoft.com/ja-jp/library/ms228048(VS.80).aspx
方法 : ビューステートに値を保存する
http://msdn2.microsoft.com/ja-jp/library/ms227551(VS.80).aspx先ほど書きましたとおり、
キー文字列の方を共有で使用するクラスに定数としてまとめれば、入力ミス防止やIntelliSenseで入力補助ができると思います。
-
イメージ的には以下のような感じですよね?
public partial class ViewStateTest : System.Web.UI.Page
{
DataSession dsession;
protected void Page_Load(object sender, EventArgs e)
{
dsession = new DataSession();
this.Controls.Add(dsession);
}
protected void cbtn_save_Click(object sender, EventArgs e)
{
dsession["test"] = TextBox1.Text;
}
protected void cbtn_load_Click(object sender, EventArgs e)
{
Label1.Text = (string)dsession["test"];
}
}
public class DataSession : Control
{
public Object this[string strValue]
{
get { return this.ViewState[strValue]; }
set { this.ViewState[strValue] = value; }
}
}
ViewStateはコントロールが対象なので、やろうと思えば上のような感じになると思いますが、提示されたSessionのラップクラスを含め、セマンティクス的には意味が無いように思えます。
#(追記)ただ、用途によっては意味があるかもしれません・・・
すべての返信
-
なかなか光が見えてきませんが・・・
やはり例えば以下の様に、地道にプロパティを記述するしかないのでしょうか
よろしくお願いします。
public int Counter
{
get
{
object objCounter = ViewState["btnCounter"];
int CounterClick = 0;
if (objCounter != null)
CounterClick = (int)objCounter;
return CounterClick;
}
set
{
ViewState["btnCounter"] = value;
}
} -
marumusisan さんからの引用 System.Web.UI.Pageを継承したスーパークラスを作成する事はよくあると思いますが、
その際にSessionやFormデータ等いろいろと格納するケースがあると思われます。
ViewStateでも最初のご投稿でSessionについて書かれてるようにすればよいのではないでしょうか。
MSDNライブラリの以下のページのサンプルにもそれと似てるのがありますし。
StateBag クラス
http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx
-
アドバイスありがとうございます。
確かにおっしゃる通りなのですが
public Object this[String strKey]
{
get
{
object o = ViewState[strKey];
return (o == null)? String.Empty : (string)o;}
set
{
ViewState[strKey] = value;
}
}こんな感じでコード書いてもコンパイルが通るはずもなく・・・
エラー 598 名前 'ViewState' は現在のコンテキスト内に存在しません。
私が理解できていないのが原因なのですけど。
良きアドバイス頂ければ幸いです。
-
ViewState というのはリクエストされたページに「固有のデータ」ですよね。データをクラスにしてしまおうという設計はちょっと変じゃないでしょうか。個人的には Session もそのようにクラスでラップするのは扱いづらいです。
例えば、marumusisan さんが言うようにスーパークラスに ViewState のプロパティを定義したとしましょう。
この場合、単に「同じ名前のビューステート」であって「同じビューステート値」ではないですよね?各々のページで値は違います。
同じようにスーパークラスにセッションのプロパティを定義したとしましょう。
この場合、全てのページで「同じ名前のセッション」であり、且つ「同じセッション値」になります。
ビューステートやセッションはそういうものだから混乱しないですが、クラスやプロパティでラップしてしまうとビューステートやセッションである事が隠されてしまい混乱の元になるでしょう。折角ラップしても、ビューステートなのかセッションなのかをいちいち意識していないといけません。
という事で、私はせいぜい private なプロパティにラップするに留めるか、そのまま Session プロパティや ViewState プロパティに直接アクセスする(インデクサの文字列は定数にしていても良い)事が望ましいと思います。 -
そこで、恐縮なのですが、技術的に可能なのかどうかをご教示頂けますか。
後学の為に知りたいと考えています。あ、すみません。質問に全く答えていない事に今気付きました。質問に答えていないのにグダグダ言ってもしょうがありませんよね。
Session のようにはいきません。
Page.Session は単に HttpContext.Current.Session を参照しているだけですが、
先述したように ViewState はあくまで Page のデータです。
さらに、ViewState は protected なので以下のようにもできません。Code Snippetpublic class DataViewState{
private Page _page;public DateViewState(Page page){
_page = page;
}public string Hoge{
get{ return (string)_page.ViewState["Hoge"]; }
}
}という事で無理です。
-
marumusisan さんからの引用 public Object this[String strKey]
{
get
{
object o = ViewState[strKey];
return (o == null)? String.Empty : (string)o;}
set
{
ViewState[strKey] = value;
}
}たとえコンパイル通っても無意味だと思います。ラップになっていません。
#インデクサでしたか…プロパティにするのかと思ってました。
プロパティにするなら先ほど書いた
StateBag クラス
http://msdn2.microsoft.com/ja-jp/library/system.web.ui.statebag(VS.80).aspx
のサンプルのようにするのではダメでしょうか。
ViewState はページ固有のデータなので、他からアクセスすることは考えられないので、やはり囚人様が仰せになるとおり、Session プロパティや ViewState プロパティに直接アクセスするのがいいと思います。
方法 : ビューステートから値を読み取る
http://msdn2.microsoft.com/ja-jp/library/ms228048(VS.80).aspx
方法 : ビューステートに値を保存する
http://msdn2.microsoft.com/ja-jp/library/ms227551(VS.80).aspx先ほど書きましたとおり、
キー文字列の方を共有で使用するクラスに定数としてまとめれば、入力ミス防止やIntelliSenseで入力補助ができると思います。
-
イメージ的には以下のような感じですよね?
public partial class ViewStateTest : System.Web.UI.Page
{
DataSession dsession;
protected void Page_Load(object sender, EventArgs e)
{
dsession = new DataSession();
this.Controls.Add(dsession);
}
protected void cbtn_save_Click(object sender, EventArgs e)
{
dsession["test"] = TextBox1.Text;
}
protected void cbtn_load_Click(object sender, EventArgs e)
{
Label1.Text = (string)dsession["test"];
}
}
public class DataSession : Control
{
public Object this[string strValue]
{
get { return this.ViewState[strValue]; }
set { this.ViewState[strValue] = value; }
}
}
ViewStateはコントロールが対象なので、やろうと思えば上のような感じになると思いますが、提示されたSessionのラップクラスを含め、セマンティクス的には意味が無いように思えます。
#(追記)ただ、用途によっては意味があるかもしれません・・・