WebSurfer's Home

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

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

by WebSurfer 2016年10月13日 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 2012年5月26日 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

ListView に配置した CheckBox で選択

by WebSurfer 2012年3月17日 17:03

ユーザーが ListView 上の CheckBox にチェックを入れて複数の項目を選択後、ポストバックしてサーバー側で選択された項目を取得するという例です。

ListView に配置した CheckBox の選択結果をサーバーで取得

特に難しいことではないのですが、GridView と違って、ListView の場合はあまり例が見つからないので、忘れないように書いておきます。

ListView は「項目」(ListViewItem オブジェクト)で構成されており、そのコレクションは Items プロパティで取得できます。

後はループを回して、ListViewItem オブジェクトの中から FindControl メソッドで CheckBox オブジェクトを探し、チェックがついているかどうかを調べることができます。

そのサンプルコードは以下の通りです。

<%@ 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 に CheckBox を追加。ポストバックして、
  // ユーザーがチェックを入れた項目をサーバー側で取得。
    
  protected void Button1_Click(object sender, EventArgs e)
  {
    string ids = "";
    for (int i = 0; i < ListView1.Items.Count; i++ )
    {
      ListViewItem item = ListView1.Items[i];
      CheckBox cb = (CheckBox)item.FindControl("CheckBox1");
      if (cb != null)
      {
        if (cb.Checked == true)
        {
          ids += ListView1.DataKeys[i].Value.ToString() + " ";
        }
      }
    }
    Label1.Text = "Selected Products: " + ids;
  }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>ListView と CheckBox</title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:Button ID="Button1" 
      runat="server" 
      Text="PostBack" 
      OnClick="Button1_Click" />
    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind %>" 
      SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice] 
        FROM [Products] WHERE [CategoryID]=1">
    </asp:SqlDataSource>
    <asp:ListView ID="ListView1" 
      runat="server" 
      DataKeyNames="ProductID" 
      DataSourceID="SqlDataSource1">
      <EmptyDataTemplate>
        <table id="Table1" runat="server" style="">
          <tr>
            <td>
              データは返されませんでした。</td>
          </tr>
        </table>
      </EmptyDataTemplate>

      <ItemTemplate>
        <tr style="">
          <td>
            <asp:CheckBox ID="CheckBox1" 
              runat="server" />
          </td>
          <td>
            <asp:Label ID="ProductIDLabel" 
              runat="server" 
              Text='<%# Eval("ProductID") %>' />
          </td>
          <td>
            <asp:Label ID="ProductNameLabel" 
              runat="server" 
              Text='<%# Eval("ProductName") %>' />
          </td>
          <td>
            <asp:Label ID="UnitPriceLabel" 
              runat="server" 
              Text='<%# Eval("UnitPrice") %>' />
          </td>
        </tr>
      </ItemTemplate>

      <LayoutTemplate>
        <table id="Table2" runat="server">
          <tr id="Tr1" runat="server">
            <td id="Td1" runat="server">
              <table ID="itemPlaceholderContainer" 
                runat="server" 
                border="0" 
                style="">
                <tr id="Tr2" runat="server" style="">
                  <th id="Th1" runat="server">
                    Select</th>
                  <th id="Th2" runat="server">
                    ProductID</th>
                  <th id="Th3" runat="server">
                    ProductName</th>
                  <th id="Th4" runat="server">
                    UnitPrice</th>
                </tr>
                <tr ID="itemPlaceholder" runat="server">
                </tr>
              </table>
            </td>
          </tr>
          <tr id="Tr3" runat="server">
            <td id="Td2" runat="server" style="">
            </td>
          </tr>
        </table>
      </LayoutTemplate>

    </asp:ListView>
  </div>
  <asp:Label ID="Label1" runat="server"></asp:Label>
  </form>
</body>
</html>

Tags: ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2017年4月  >>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

View posts in large calendar