WebSurfer's Home

Filter by APML

ListView でページ指定

by WebSurfer 13. November 2010 16:25
ListView でページ指定

GridView や ListView でページングを行っている場合、プログラムで表示するページを指定したいケースがあると思います。

GridView の場合は簡単で、PageIndex プロパティを用いてページの指定ができます。

ところが、ListView には、GridView の PageIndex プロパティのような、表示するページを指定できるプロパティがありません。

これは、GirdView にはページング機能が統合されているのに対し、ListView そのものにはページング機能は実装されていないからです。

通常、ListView でページングを行うには、DataPager コントロールを用います。これを利用すれば、GridView.PageIndex プロパティと同様に、ListView でもプログラムで表示するページを指定することができます。

以下に、ListView において、プログラムで表示するページを指定する例を書いておきます。

まず、DataPager フィールドに NumericPagerField クラスを実装する必要があります。その HandleEvent メソッドを利用します。

HandleEvent メソッドは、引数の CommandEventArgs オブジェクトの CommandName プロパティの値を見て、それにページ番号が指定されている場合、対応するページに移動させます。

上の画像のサンプルのコードは以下の通りです。TextBox にページ番号を入力してボタンをクリックすると、指定したページに飛びます。

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  protected void Button1_Click(object sender, EventArgs e)
  {
    int page = 0;
    if (Int32.TryParse(TextBox1.Text, out page))
    {
      page -= 1;
    }
    CommandEventArgs commandEventArgs = 
      new CommandEventArgs(page.ToString(), "");
    DataPager dp = 
      (DataPager)ListView1.FindControl("DataPager1");
    NumericPagerField numericPagerField = 
      dp.Fields[2] as NumericPagerField;
    if (numericPagerField != null)
    {
      numericPagerField.HandleEvent(commandEventArgs);
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
  <style type="text/css">
    table.style1
    {
      border-style: solid;
      border-width: 2px;
      border-color: Black;
      text-align: center;
      border-collapse: collapse;
    }
       
    table.style1 th
    {
      border-style: solid;
      border-width: 2px 1px 2px 1px;
      border-color: Black;
      background-color: #6699FF;
      color: #FFFFFF;
    }
        
    table.style1 td
    {
      border-style: solid;
      border-width: 1px;
      border-color: Black;        
    }
  </style>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    Page: 
    <asp:TextBox ID="TextBox1" runat="server">
    </asp:TextBox>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="Go" 
      OnClick="Button1_Click" />
    <hr />
    <asp:ObjectDataSource ID="ObjectDataSource1" 
      runat="server" 
      EnablePaging="True" 
      SelectCountMethod="GetNumberOfMessages" 
      SelectMethod="GetDataByIndex" 
      TypeName="OrdersDataSetTableAdapters.OrdersTableAdapter">
      <SelectParameters>
        <asp:Parameter Name="employeeid" DefaultValue="-1" />
      </SelectParameters>
    </asp:ObjectDataSource>
    <asp:ListView ID="ListView1" 
      runat="server" 
      DataKeyNames="OrderID" 
      DataSourceID="ObjectDataSource1">
      <LayoutTemplate>
        <table runat="server">
          <tr runat="server">
            <td runat="server">
              <table ID="itemPlaceholderContainer" 
                runat="server" 
                class="style1">
                <tr runat="server">
                  <th id="Th1" runat="server">
                    OrderID</th>
                  <th id="Th2" runat="server">
                    CustomerID</th>
                  <th id="Th3" runat="server">
                    OrderDate</th>
                  <th id="Th4" runat="server">
                    Freight</th>
                  <th id="Th5" runat="server">
                    ShipCountry</th>
                </tr>
                <tr ID="itemPlaceholder" 
                  runat="server">
                </tr>
              </table>
            </td>
          </tr>
          <tr runat="server">
            <td runat="server">
              <asp:DataPager ID="DataPager1" 
                runat="server" 
                PageSize="10">
                <Fields>
                  <asp:TemplatePagerField>              
                    <PagerTemplate>
                      <b>
                        Page
                        <asp:Label runat="server" 
                          ID="CurrentPageLabel" 
                          Text="<%# Container.TotalRowCount>0 ? (Container.StartRowIndex / Container.PageSize) + 1 : 0 %>" />
                        of
                        <asp:Label runat="server" 
                          ID="TotalPagesLabel" 
                          Text="<%# Math.Ceiling ((double)Container.TotalRowCount / Container.PageSize) %>" />
                        (
                        <asp:Label runat="server" 
                          ID="TotalItemsLabel" 
                          Text="<%# Container.TotalRowCount%>" />
                        records)
                        <br />
                      </b>
                    </PagerTemplate>
                  </asp:TemplatePagerField>
                  <asp:NextPreviousPagerField
                    ButtonType="Button"
                    ShowFirstPageButton="true"
                    ShowNextPageButton="false"
                    ShowPreviousPageButton="false" />
                  <asp:NumericPagerField 
                    PreviousPageText="< Prev 5"
                    NextPageText="Next 5 >"
                    ButtonCount="5" />
                  <asp:NextPreviousPagerField
                    ButtonType="Button"
                    ShowLastPageButton="true"
                    ShowNextPageButton="false"
                    ShowPreviousPageButton="false" />
                </Fields>
              </asp:DataPager>
            </td>
          </tr>
        </table>
      </LayoutTemplate>
      <ItemTemplate>
                <tr>
                  <td>
                    <asp:Label ID="OrderIDLabel" 
                     runat="server" 
                     Text='<%# Eval("OrderID") %>' />
                  </td>
                  <td>
                    <asp:Label ID="CustomerIDLabel" 
                     runat="server" 
                     Text='<%# Eval("CustomerID") %>' />
                  </td>
                  <td>
                    <asp:Label ID="OrderDateLabel" 
                     runat="server" 
                     Text='<%# Eval("OrderDate", "{0:yyyy/MM/dd}") %>' />
                  </td>
                  <td>
                    <asp:Label ID="FreightLabel" 
                     runat="server" 
                     Text='<%# Eval("Freight", "${0:N2}") %>' />
                  </td>
                  <td>
                    <asp:Label ID="ShipCountryLabel" 
                     runat="server" 
                     Text='<%# Eval("ShipCountry") %>' />
                  </td>
                </tr>
      </ItemTemplate>
    </asp:ListView>    
  </div>
  </form>
</body>
</html>

なお、上記は Resetting the Page Index in a ListView を参考にしています(参考というよりほぼ丸写しですが)。

Tags: , ,

Paging

GridView, ListView に合計表示

by WebSurfer 7. November 2010 19:04
ListView に合計を表示

GirdView や ListView で、ある列の合計金額を計算して、フッターなどに表示したいというケースが時々あります。備忘録として、その例を書いておきます。

GridView は「行」(GridViewRow クラス)で構成されているのに対して、ListView は「項目」(ListViewItem クラス)で構成されているという違いがありますが、基本的な方法は行/項目にデータがバインドされるときのイベントを利用して、値を取得して合計していくという操作は同じだと思います。

GridView, ListView どちらの場合も、データソースコントロールが取得してバインドするデータが DataTable の場合(デフォルト)は、DataItem プロパティを使って DataRowView を取得できますので、それから各行/項目の値を取得するのがよさそうです。

合計した結果を書き込むところが、ちょっと違います。

GridView では、フッターでも RowDataBound イベントが発生します。そのイベントハンドラでデータ行かフッター行かが判定でき、フッター行の場合に合計をフッターに書き込むことができます。

ShowFooter="True" として、その中の TableCell の Text プロパティに書き込む例は以下の通りです。

decimal total = 0m;
    
protected void GridView1_RowDataBound(object sender, 
  GridViewRowEventArgs e)
{        
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
    DataRowView drv = (DataRowView)e.Row.DataItem;
    total = total + (decimal)drv["Freight"];
  }
  else if (e.Row.RowType == DataControlRowType.Footer)
  {
    e.Row.Cells[1].Text = "Freight Total";
    e.Row.Cells[2].Text = String.Format("${0:N2}", total);
  }        
}

ListView では、合計の取得は ItemDataBound イベントハンドラで可能ですが、GridView の時のようにフッター行に合計結果を書き込むことはできません。

LayoutTemplate にフッターの行を追加して Label を配置し、その Text プロパティに書き込むことになります。そのタイミングは、ListView.DataBound イベントがよさそうです。

上の画像を出力した ListView のコードを以下にアップしておきます。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  decimal total = 0m;
    
  protected void ListView1_ItemDataBound(object sender, 
      ListViewItemEventArgs e)
  {
    if (e.Item.ItemType == ListViewItemType.DataItem)
    {
      ListViewDataItem lvdi = (ListViewDataItem)e.Item;
      DataRowView drv = (DataRowView)lvdi.DataItem;
      total = total + (decimal)drv["Freight"];
    }
  }

  protected void ListView1_DataBound(object sender, EventArgs e)
  {
    Label label = (Label)ListView1.FindControl("totalLabel");
    label.Text = String.Format("${0:N2}", total);
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Show Total in ListView</title>
  <style type="text/css">
    table.style1
    {
      border-style: solid;
      border-width: 2px;
      border-color: Black;
      text-align: center;
      border-collapse: collapse;
    }
       
    table.style1 th
    {
      border-style: solid;
      border-width: 2px 1px 2px 1px;
      border-color: Black;
      background-color: #6699FF;
      color: #FFFFFF;
    }
        
    table.style1 td
    {
      border-style: solid;
      border-width: 1px;
      border-color: Black;        
    }
        
    .footer
    {
      background-color: #CCFFFF;
    }  
  </style>

</head>
<body>
  <form id="form1" runat="server">
  <div>
    <h3>Alfreds Futterkiste</h3>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind %>" 
      SelectCommand="SELECT [OrderID], [OrderDate], [Freight] 
        FROM [Orders] 
        WHERE [CustomerID]='ALFKI'">            
    </asp:SqlDataSource>
    <asp:ListView ID="ListView1" 
      runat="server" 
      DataKeyNames="OrderID" 
      DataSourceID="SqlDataSource1" 
      EnableModelValidation="True" 
      OnItemDataBound="ListView1_ItemDataBound" 
      OnDataBound="ListView1_DataBound">
      <ItemTemplate>
        <tr>
          <td>
            <asp:Label ID="OrderIDLabel" 
              runat="server" 
              Text='<%# Eval("OrderID") %>' />
          </td>
          <td>
            <asp:Label ID="OrderDateLabel" 
              runat="server" 
              Text='<%# Eval("OrderDate", "{0:yyyy/MM/dd}") %>' />
          </td>
          <td style="text-align: right;">
            <asp:Label ID="FreightLabel" 
              runat="server" 
              Text='<%# Eval("Freight", "${0:N2}") %>' />
          </td>
        </tr>
      </ItemTemplate>
      <LayoutTemplate>
        <table ID="itemPlaceholderContainer" 
          runat="server" 
          class="style1">
          <tr runat="server">
            <th runat="server">
              OrderID</th>
            <th runat="server">
              OrderDate</th>
            <th runat="server">
              Freight</th>
          </tr>
          <tr ID="itemPlaceholder" runat="server">
          </tr>
          <tr class="footer">
            <td></td>
            <td>Freight Total</td>
            <td style="text-align: right;">
              <asp:Label ID="totalLabel" runat="server" /></td>
          </tr>
        </table>                        
      </LayoutTemplate>
    </asp:ListView>
  </div>
  </form>
</body>
</html>

Tags: ,

ASP.NET

ListView と DropDownList

by WebSurfer 31. October 2010 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

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。ブログ2はそれ以外の日々の出来事などのトピックスになっています。

Calendar

<<  October 2026  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar