WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ListView と DropDownList

by WebSurfer 2010年10月31日 19:32

ListView の InsertItemTemplate に DropDownList を配置し、DropDownList.SelectedValue を DB に挿入するにはどのようにすればよいかという話です。ただし、.NET 4 では問題なく、.NET 3.5 に限った話です。

何故かは不明ですが、InsertItemTemplate に DropDownList を配置した場合は、DropDownList の SelectedValue プロパティを以下のように設定してもうまくいきません。「Eval()、XPath()、および Bind() のようなデータバインド メソッドは、データバインドされたコントロールのコンテキストでのみ使用することができます。」というエラーになります。

<InsertItemTemplate>
  <tr style="">
  ・・・中略・・・
    <td>
      <asp:SqlDataSource ID="SqlDataSource1" ・・・
      ・・・中略・・・
      <asp:DropDownList ID="DropDownList1" 
        runat="server"
        DataSourceID="SqlDataSource1" 
        DataTextField="CategoryName" 
        DataValueField="CategoryName"
        AppendDataBoundItems="True"
        SelectedValue='<%# Bind("memo") %>'>
        <asp:ListItem Value="">空白</asp:ListItem>
      </asp:DropDownList>
    </td>
  </tr>
</InsertItemTemplate>

なお、上記と同様な形で EditItemTemplate に配置した場合は問題なく、DB は SelectedValue でちゃんと更新されます。

この問題の回避策は、以下のように SqlDataSource.Inserting イベントハンドラで処置することです。

protected void SqlDataSource1_Inserting(object sender, 
    SqlDataSourceCommandEventArgs e)
{
  DropDownList ddl = 
    (DropDownList)ListView1.InsertItem.FindControl("DropDownList1");
  e.Command.Parameters["@memo"].Value = ddl.SelectedValue;
}

何故、InsertItemTemplate に DropDownList を配置した場合ダメなのかが分からなかったし、もっとスマートな解決策があるのではないか(ひょっとして、とんでもなく間抜けなのことしているのではないか)ということが気になっていましたが、どうやら .NET 3.5 のバグらしいということで、安心(?)しています。(笑)

Tags: ,

ASP.NET

DataPager のバグその2

by WebSurfer 2010年10月30日 14:34

先のポスト DataPager のバグその1 に続いて、再び DataPager のバグの話です。なお、このバグも .NET 4 では修正されており、.NET 3.5 のみの問題です。

ListView の中に配置した DataPager の設定にある条件が重なると Stack Overflow を起こします。条件というのは以下の 5 つです。

  1. ListView の LayoutTemplate の中に DataPager を配置
  2. ListView に EmptyDataTemplate を配置
  3. ListView にバインドされるデータの件数が 0
  4. DataPager.QueryStringField を設定(例: QueryStringField="pageNumber")
  5. そのページを、クエリ文字列 ?pageNumber=1 として要求

残念ながら原因は分かりません。(涙)

でも、回避策は簡単で、DataPager を ListView の外に出してしまえばいいのです。件数 0 の場合は ListView の外に DataPager を配置しても、それが表示されることはないです。

または、当然ながら、DataPager.QueryStringField の設定を止めても回避できます。DataPager.QueryStringField を使う理由が、GridView.PageIndex プロパティのようにコードでページを指定したいということであれば、別の手段があります。

その「別の手段」の具体的な方法は、Resetting the Page Index in a ListView が参考になると思います。

Tags:

Paging

DataPager のバグその1

by WebSurfer 2010年10月29日 23:18

.NET 3.5 で ListView コントロールと共に導入された DataPager コントロールには、QueryStringField プロパティ周りにバグがあります。

QueryStringField プロパティというのは、クエリ文字列を利用してページの移動先を指定し、ページの移動に HTTP GET コマンド(デフォルトでは POST)を使用できるようにするためのものです。

例えば、QueryStringField="pageNumber" と設定した場合、ページャーをクリックして指定した移動先のページ番号が 5 であったとすると、URL にクエリ文字列 ?pageNumber=5 を追加して HTTP GET コマンドでそのページを要求するようになります。

MSDN ライブラリ「DataPager.QueryStringField プロパティ」によると "検索エンジンですべてのデータ ページにインデックスが付けられるようにするには、このプロパティを設定すると便利です。" とのことです。

ところが、このページを要求する際に、クエリ文字列のキーに null が含まれる場合(例えば、?pageNumber=5& とすると、& の後に null のキーがあると判断されるようです)、NullReferenceException がスローされるという問題があります。

ページ内でページャーをクリックしているだけなら、自動的に ?pageNumber=x (x は要求するページ番号)というクエリ文字列が URL に追加されて要求がかかるので間違いなく動作しますが、別のページでクエリ文字列を組み立ててそのページを要求する場合、間違って ?pageNumber=x& などとすると例外がスローされます

この問題は、2008 年 7 月に Connect に報告されています。

この報告によると、受信したクエリ文字列のキーに null が含まれていると、ライブラリ内のメソッドの以下の部分で key(String オブジェクト)が null になって NullReferenceException がスローされるということだそうです。これはバグとして次期バージョンで修正されるという話になっていました。

foreach (string key in request.QueryString.AllKeys)
{
  if (... && !key.Equals(queryStringField, 
                StringComparison.OrdinalIgnoreCase))

今日、このページをのぞいてみたら、すでに修正済みというようなことが書いてあります。ということは、少なくとも .NET 4 では修正されているはずです。

ということで、早速試してみました。結果は:

  • .NET 3.5 SP1: ダメでした。NullReferenceException がスローされます。
  • .NET 4: 例外はスローされなかったので、バグは修正されているようです。

というわけで、ASP.NET 3.5 では回避策がまだ必要なようです。上に紹介した Connect のページに回避策も提案されていますので、そちらを参照してください。

Tags:

Paging

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年5月  >>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar