WebSurfer's Home

Filter by APML

ListView に thead と tbody 追加

by WebSurfer 1. April 2024 13:11

ASP.NET Web Forms アプリ用の ListView コントロールからレンダリングされる html ソースの table 要素内に thead, tbody 要素を追加する方法を書きます。

Visual Studio のデザイナを使って ListView のテーブル形式のコードを自動生成させると aspx ファイルに以下のような LayoutTemplate が生成されます。まず、それに赤枠と青枠で示したような thead, tbody 要素を追記します。

aspx ファイル

さらに、自動生成されたコードでは親の table 要素に runat="server" 属性が付与されているのでそれを削除する必要があります。上の画像のコメントを見てください。

runat="server" 属性が付与されているとその要素はサーバーコントロールになります。親の table 要素がサーバーコントロールになると、ASP.NET が html ソースをレンダリングする際に追加した thead, tbody 要素は削除されてしまいますので。

結果の html ソースは以下のようになります。

結果の html ソース

runat="server" 属性を削除するとサーバー側のコードでその要素を操作(例えばプロパティを動的に設定するなど)できなくなりますが、それ以外の不都合はないと思います。

GridView の例は別の記事「GridView と thead, tbody, tfoot」に書きましたのでそちらを見てください。

Tags: , ,

ASP.NET

GridView, ListView で特定の行をハイライト

by WebSurfer 13. October 2016 23:35

GridView, ListView でデータを一覧表示する際、それにデータバインドされたデータソースに含まれる各行の特定の列のデータの値を調べ、その値に応じて当該行をハイライトする方法について書きます。

元は MSDN フォーラムのスレッド「ListViewでの一覧表示で、取得したデータに応じて背景色を変えたい」での話です。

そのスレッドで自分が回答したことなのですが、忘れかけていたので自分のブログに備忘録として書いておくことにしました。また、ついでに GridView での実装例も書いておきます。

このブログの別の記事「GridView, ListView に合計表示」のコードをベースにしていますので、そちらも見てください。

その記事では、Microsoft が提供するサンプルデータベース Northwind の Orders というテーブルのレコードのうち、[CustomerID] が ALFKI という顧客の注文の [OrderID], [OrderDate], [Freight] フィールド一覧を表示しています。

Orders テーブルには出荷日を示す [ShippedDate] というフィールドが含まれています。ここでは、[ShippedDate] を調べて、ある日付より後に出荷されたレコードの行の背景色をハイライトしてみます。なお、ListView / GridView には [ShippedDate] フィールドは表示しません。

ListView での例

以下の画像は 1998/1/1 より後に出荷された注文のレコードをハイライトしたものです。

ListView

紹介した MSDN フォーラムのスレッドで書いたとおりですが、上のように表示するための具体的な方法を以下に書きます。

  1. SqlDataSource の SELECT クエリに [ShippedDate] を追加します。
  2. ListView の ItemTemplate 内の tr 要素をサーバーコントロールに変更して id を付与します。具体的には runat="server" id="datarow" という 2 つの属性を追加します(id 名は任意)。
  3. 例えば、1998/1/1 より後に出荷されたレコードを黄色でハイライトする場合、[ShippedDate] が 1998/1/1 より後のアイテムの中から FindControl メソッドで上記 2 でサーバーコントロールにした tr 要素を探し、それに style 属性を追加します。コードは以下のようになります。
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"];

    // 以下が追加した部分
    DateTime date = new DateTime(1998, 1, 1, 0, 0, 0);
    if ((DateTime)drv["ShippedDate"] > date)
    {
      HtmlControl tr = (HtmlControl)lvdi.FindControl("datarow");
      if (tr != null)
      {
        tr.Attributes.Add("style", "background-color:yellow;");
      }
    }
  }
}

GridView での例

上の ListView の場合と同様に、1998/1/1 より後に出荷された注文のレコードをハイライトしたものです。

GridView

上のように表示するための具体的な方法は以下の通りです。

  1. SqlDataSource の SELECT クエリに [ShippedDate] を追加します。(ListView の場合と同様)
  2. ListView の場合とは異なり、GridView のコードには手を加える必要はありません。GridView の RowDataBound イベントで GridViewRow を取得し、それの CssClass プロパティにスタイルを設定できますので。
  3. 上の ListView の場合と同様に、1998/1/1 より後に出荷されたレコードを黄色でハイライトする場合、[ShippedDate] を調べて 1998/1/1 より後であれば、当該行の GridViewRow オブジェクトを取得し、その CssClass プロパティを設定します。コードは以下のようになります。
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"];

    // 以下が追加した部分
    DateTime date = new DateTime(1998, 1, 1, 0, 0, 0);
    if ((DateTime)drv["ShippedDate"] > date)
    {
      e.Row.CssClass = "style1";
    }
    // ここまで
  }
  else if (e.Row.RowType == DataControlRowType.Footer)
  {
    e.Row.Cells[1].Text = "Freight Total";
    e.Row.Cells[2].Text = String.Format("${0:N2}", total);

    e.Row.Cells[1].ColumnSpan = 2;
    e.Row.Cells.RemoveAt(0);            
  }        
}

e.Row.CssClass = "style1"; のところの style1 は別途定義してソースに追加してください。インラインで <title> 要素の下に書くなら以下のようにします。

<style type="text/css">
    .style1
    {
        background-color: yellow;
    }
</style>

Tags: , ,

ASP.NET

ListView でソート(行の並び替え)

by WebSurfer 26. May 2012 15:35

ListView で、ヘッダのリンクボタンをクリックして、その列に設定した SortExpression に従って行の並べ替えを行う例です。

ListView でソート(列の並べ替え)を行う例

GridView の場合は、ウィザードを使ってコードは一行も書かないで簡単にできますが、ListView では少しですが自力でコードを書かなければなりません。

GridView の場合は AllowSorting プロパティを true に設定すれば、ヘッダが自動的に LinkButton になって、それをクリックすれば、その列に設定した SortExpression に従って列の並べ替えが行われます。

ところが、ListView には AllowSorting プロパティという便利なものはありません。ウィザードで作っていくと、ヘッダは普通のテキストになりますので、それを自力で LinkButton に置き換えて、Text、CommandName、CommandArgument の各プロパティを設定してやる必要があります。

Text にはヘッダに表示するテキスト、CommandName は Sort、CommandArgument は SortExpression を設定します。以下のコード例を参考にしてください。それだけで、GridView と同様な列の並べ替えが可能になります。

昇順/降順を示すイメージをヘッダのテキストに追加して表示する場合は、MSDN ライブラリの ListView.Sorting イベント のページのコードが参考になると思います。

以下、余談かもしれませんが、気がついたポイントを書いておきます。

SortExpression は複数の列を指定することもできます。例えば、A, B, C 列があるとすると、C 列の SortExpression を A, B, C のようにすることも可能です。LinkButton のクリックを繰り返すと、昇順/降順が切り替わりますが、ASC/DESC は SortExpression の末尾に追加されます(A, B, C DESC のように)。

SQL Server に投げられるクエリに ORDER BY xxxxx が追加されることはありません(プロファイラで見ると分かりますが、ヘッダの LinkButton をクリックすると、SqlDataSource の SelectCommand に設定されたクエリが毎回そのまま投げられます)。ListView と SqlDataSource の中でどのような操作が行われているかは見えないので定かではないですが、たぶん、取得したデータから DataView を作って、その Sort プロパティ に SortExpression を設定し、ソートした結果を ListView に表示しているようです。(これは GridView の場合も同じです)

SqlDataSource.DataSourceMode は DataSet でなければなりません。DataReader では、ソートを行うために LinkButton をクリックすると、System.NotSupportedException がスローされます。

以下にコード例をアップしておきます。上の画像の ListView を表示したコードです。

<%@ 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">
  // ListView でソートするサンプル

  protected void Button1_Click(object sender, EventArgs e)
  {
    // 初期状態に戻すには SortExpression を "" にして
    // ListView.Sort メソッドを実行する。(GridView で
    // も同様)
    ListView1.Sort("", SortDirection.Ascending);
  }
</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;
      padding: 0px 5px 0px 5px;
    }
        
    table.style1 td
    {
      border-style: solid;
      border-width: 1px;
      border-color: Black;
      padding: 0px 5px 0px 5px;
    }
  </style>

</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="初期状態に戻す" 
      OnClick="Button1_Click" />

    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind2 %>" 
      SelectCommand=
        "SELECT SupplierID, CategoryID, UnitPrice, ProductName 
        FROM Products" 
      DataSourceMode="DataSet">
    </asp:SqlDataSource>

    <asp:ListView ID="ListView1" 
      runat="server" 
      DataSourceID="SqlDataSource1">
      <ItemTemplate>
        <tr>
          <td>
            <asp:Label ID="SupplierIDLabel" runat="server" 
              Text='<%# Eval("SupplierID") %>' />
          </td>
          <td>
            <asp:Label ID="CategoryIDLabel" runat="server" 
              Text='<%# Eval("CategoryID") %>' />
          </td>
          <td>
            <asp:Label ID="UnitPriceLabel" runat="server" 
              Text='<%# Eval("UnitPrice") %>' />
          </td>
          <td>
            <asp:Label ID="ProductNameLabel" runat="server" 
              Text='<%# Eval("ProductName") %>' />
          </td>
        </tr>
      </ItemTemplate>
      <LayoutTemplate>
        <table>
          <tr>
            <td>
              <table ID="itemPlaceholderContainer" 
                runat="server" 
                class="style1">
                <tr>
            <%--ソーティングのためヘッダーのテキストを LinkButton 
               に置き換える。CommandName を Sort に設定し、
              CommandArgument を SortExpression に設定。--%>
                  <th>
                    <asp:LinkButton ID="LinkButton1" 
                      runat="server" 
                      Text="SupplierID" 
                      CommandName="Sort" 
                      CommandArgument="SupplierID" />
                  </th>
                  <th>
                    <asp:LinkButton ID="LinkButton2" 
                      runat="server" 
                      Text="CategoryID" 
                      CommandName="Sort" 
                      CommandArgument="SupplierID,CategoryID" />
                  </th>
                  <th>
                    <asp:LinkButton ID="LinkButton3" 
                      runat="server" 
                      Text="UnitPrice" 
                      CommandName="Sort" 
                      CommandArgument=
                        "SupplierID,CategoryID,UnitPrice" />
                  </th>
                  <th>
                    <asp:LinkButton ID="LinkButton4" 
                      runat="server" 
                      Text="ProductName" 
                      CommandName="Sort" 
                      CommandArgument="ProductName" />
                  </th>
                </tr>
                <tr runat="server" ID="itemPlaceholder">
                </tr>
              </table>
            </td>
          </tr>
          <tr>
            <td>
            <%--以下はオマケのちょっと凝ったページャー。--%>
              <asp:DataPager ID="DataPager1" runat="server">
                <Fields>
                  <asp:TemplatePagerField>              
                    <PagerTemplate>
                      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 />
                    </PagerTemplate>
                  </asp:TemplatePagerField>
                                    
                  <asp:NextPreviousPagerField
                    ButtonType="Button"
                    ShowFirstPageButton="true"
                    ShowNextPageButton="false"
                    ShowPreviousPageButton="false" />
                  <asp:NumericPagerField 
                    PreviousPageText="< Prev 3"
                    NextPageText="Next 3 >"
                    ButtonCount="3" />
                  <asp:NextPreviousPagerField
                    ButtonType="Button"
                    ShowLastPageButton="true"
                    ShowNextPageButton="false"
                    ShowPreviousPageButton="false" />
                </Fields>
              </asp:DataPager>
            </td>
          </tr>
        </table>
      </LayoutTemplate>
    </asp:ListView>
  </div>
  </form>
</body>
</html>

Tags: ,

ASP.NET

About this blog

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

Calendar

<<  December 2024  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar