none
ListViewでの一覧表示で、取得したデータに応じて背景色を変えたい RRS feed

  • 質問

  • Webフォームで一覧照会の画面を ListView + DataPager + ObjectDataSource で作っているのですが、
    行データの値に応じて、セルの背景色を変えたいという要望があります。

    いろいろと調べてみましたが、GridViewだったらできるようなことも書いてありましたが
    明細が2行で1件分のデータ表示をしているため、いまさらGridViewに変えるわけにもいかず
    困っております。

    当方、ASP.NET の経験が浅く、できるのかできないのかの判断も付きません。

    できる、できないの判断だけでも結構ですので、どなたかヒントをいただけないでしょうか。

    2014年9月4日 17:41

回答

  • > 表示しても問題ないです。

    表示する必要はないです。

    前のレスで紹介した「GridView, ListView に合計表示」というページの ListView のコードを例にとって説明します。(このコードは SqlDataSource を使ってますが、ObjectDataSource でも同じことができます)

    Microsoft が提供するサンプル DB の Northwind の Orders というテーブルを使ってますが、この中には [OrderID], [OrderDate], [Freight] の他に [ShippedDate] というフィールドがあります。

    この [ShippedDate] は ListView には表示しないが、この日付によって背景色を変えるとします。

    (1) SqlDataSource の SELECT クエリに [ShippedDate] を追加します。

    (2) ListView の ItemTemplate 内の tr 要素をサーバーコントロールに変更して id を付与します。具体的には runat="server" id="datarow" という 2 つの属性を追加します。

    (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: #EEEEEE;");
                }
            }
        }
    }

    • 回答としてマーク Ticky4649 2014年9月5日 9:42
    2014年9月5日 5:54

すべての返信

  • 一行おきで良いのであれば、AlternatingItemTemplate に CSS を適用してはいかがですか?

    以下のような感じです。コードの中の class="alternate" に注目してください。

    ObjectDataSource でページング
    http://surferonwww.info/BlogEngine/post/2010/08/26/Paging-with-ObjectDataSource.aspx

    そうではなくて、

    > 行データの値に応じて、セルの背景色を変えたいという要望があります。

    データバインドされた時に値を調べて・・・ということでしたら、もっと具体的にどうしたいのか書いてください。

    2014年9月5日 0:07
  • SurferOnWwwさん

    レスありがとうございます。

    わかりにくくて申し訳ありません。

    簡単にいうと一覧表示で明細行の背景色を変えたいのですが、単純に交互に変えるだけなら AlternateItemTemplate でできるのですが、データ値に依存して変更したいのです。

    ObjectDataSourceで取得した列のある項目=1なら、行の背景色をブルーにする。それ以外なら行の背景色をグリーンにするといった感じです。

    ListViewのItemTemplateが2つ定義できて、データ値によってどちらかのテンプレートを適用するようなことができればいいのですが、そのような機能はなさそうです。

    もう、ListView + DataPager で実装はほとんど終了しており、これからコントロールを変更するもの難しい状況です。

    環境は

    ・Windows Server 2008 R2 + IIS 7.5

    ・.NET Framework 3.5

    ・WebサイトプロジェクトでWebフォームを使用

    です。

    2014年9月5日 1:18
  • > ObjectDataSourceで取得した列のある項目=1なら、行の背景色をブルーにする。それ以外なら
    > 行の背景色をグリーンにするといった感じです。

    その「ある項目」というのはデータバインドされる項目の一つなんですか?

    「ObjectDataSourceで取得」とのことですのでそうではないかと想像してますが。

    そうであれば、ItemDataBound イベントハンドラで DataRowView から「ある項目」の値を取得して(取得方法は以下のページ参照)、スタイルを指定するとか何とかできそうな感じがします。(今のところ感じがするだけで、まだ未検証です)

    GridView, ListView に合計表示
    http://surferonwww.info/BlogEngine/post/2010/11/07/Show-sum-in-GridView-or-ListView.aspx

    2014年9月5日 1:44
  • SurferOnWwwさん

    レスありがとうございます。

    >その「ある項目」というのはデータバインドされる項目の一つなんですか?

    はい。本来は背景色を設定するためだけに必要な項目なので、項目としては不要なのですが、

    表示しても問題ないです。

    これから外出しないといけないので、今すぐにはできないのですが、

    お教えいただいたURLを参考にして後でトライしてみます。

    ありがとうございました。

    2014年9月5日 4:32
  • きっと、以下のような感じなんですよね? 以下は良い参考になると思います。

    Defining a different background-color to the Selected Item of a asp:ListView
    http://stackoverflow.com/questions/6266342/defining-a-different-background-color-to-the-selected-item-of-a-asplistview


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2014年9月5日 4:34
    モデレータ
  • > 表示しても問題ないです。

    表示する必要はないです。

    前のレスで紹介した「GridView, ListView に合計表示」というページの ListView のコードを例にとって説明します。(このコードは SqlDataSource を使ってますが、ObjectDataSource でも同じことができます)

    Microsoft が提供するサンプル DB の Northwind の Orders というテーブルを使ってますが、この中には [OrderID], [OrderDate], [Freight] の他に [ShippedDate] というフィールドがあります。

    この [ShippedDate] は ListView には表示しないが、この日付によって背景色を変えるとします。

    (1) SqlDataSource の SELECT クエリに [ShippedDate] を追加します。

    (2) ListView の ItemTemplate 内の tr 要素をサーバーコントロールに変更して id を付与します。具体的には runat="server" id="datarow" という 2 つの属性を追加します。

    (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: #EEEEEE;");
                }
            }
        }
    }

    • 回答としてマーク Ticky4649 2014年9月5日 9:42
    2014年9月5日 5:54
  • trapemiyaさん、SurferOnWwwさん

    回答ありがとうございました。

    SurferOnWwwさんのサンプルコードを参考に実装したら首尾よく実現することができました。
    まだコードの内容が理解できていないのですが、とにかくうまくいって感動しております。

    それにしても
    >ListView の ItemTemplate 内の tr 要素をサーバーコントロールに変更して id を付与します
    などは、自分だけで考えていたのでは決して浮かんでこない発想でした。
    サンプルコードが理解できるように精進したいと思います。

    しかし、この手の処理はよくあるハズなのでネットを検索すればすぐに出てくると思ったのですが
    以外に見つからなかったところを見るとあまり一般的じゃないんでしょうかねぇ。
    「最初からMVCで作れよ」と言われそうですが。。。勉強しますMVC

    2014年9月5日 9:42