< ルート要素タグで指定されている x:TypeArguments 属性をサポートするには x:Class 属性を必要とします。 | メモ: C# プログラミング ガイド >

September 17, 2008

XmlDataProvider にバインドした ListView で、データに応じて行の背景色を変更する

bindingrowbackground.gif

XmlDataProvider にバインドしたリストビューで、行ごとにデータに応じて背景色を変えようと思い、こんな感じの実装をしてみました。

まず、Window1.xaml。

<Window x:Class="BindingRowBackgroundSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:BindingRowBackgroundSample"
    Title="データバインドで行の背景色を変える">
    <Window.Resources>
        
        <!-- リストのデータ -->
        <XmlDataProvider x:Key="SubjectListSource">
            <x:XData>
                <subjects xmlns="">
                    <subject name="国語">
                        <scores>
                            <score semester="1">88</score>
                            <score semester="2">91</score>
                        </scores>
                    </subject>
                    <subject name="数学">
                        <scores>
                            <score semester="1">24</score>
                            <score semester="2">25</score>
                        </scores>
                    </subject>
                    <subject name="理科">
                        <scores>
                            <score semester="1">100</score>
                            <score semester="2">100</score>
                        </scores>
                    </subject>
                    <subject name="社会">
                        <scores>
                            <score semester="1">65</score>
                            <score semester="2">54</score>
                        </scores>
                    </subject>
                    <subject name="英語">
                        <scores>
                            <score semester="1">28</score>
                            <score semester="2">65</score>
                        </scores>
                    </subject>
                </subjects>
            </x:XData>
        </XmlDataProvider>
        
        <!-- 行のデータから背景色を返すコンバータ -->
        <local:RowColorConverter x:Key="rowColorConverter"/>
        
        <!-- リスト行のスタイル -->
        <Style TargetType="ListViewItem" x:Key="ListViewItemStyle">
            <Setter Property="Background" Value="{Binding XPath=. Converter={StaticResource rowColorConverter}}"/>
        </Style>
    </Window.Resources>
    
    <ListView
        ItemsSource="{Binding Source={StaticResource SubjectListSource}, XPath=/subjects/subject}"
        ItemContainerStyle="{StaticResource ListViewItemStyle}">
        
        <ListView.View>
            <GridView>
                <GridViewColumn Header="教科" DisplayMemberBinding="{Binding XPath=@name}"/>
                <GridViewColumn Header="1学期" DisplayMemberBinding="{Binding XPath='scores/score[@semester=1]'}"/>
                <GridViewColumn Header="2学期" DisplayMemberBinding="{Binding XPath='scores/score[@semester=2]'}"/>
            </GridView>
        </ListView.View>
    </ListView>
</Window>

こっちが、コンバータの実装。

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace BindingRowBackgroundSample
{
    public class RowColorConverter : IValueConverter
    {
        public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var node = value as System.Xml.XmlNode;
            if (node != null)
            {
                // 1 学期と 2 学期を比較
                var sem1 = node.SelectSingleNode ("scores/score[@semester=1]");
                var sem2 = node.SelectSingleNode ("scores/score[@semester=2]");
                if (int.Parse (sem1.InnerText) > int.Parse (sem2.InnerText))
                {
                    return Brushes.Red;    // 赤いブラシを返す
                }
            }
            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException ();
        }
    }
}

実行してみると、RowColorConverter の Convert メソッドに渡される value が子孫エレメントのテキストをすべて連結した string になってしまい、XmlNode へのキャストに失敗してしまいました。何が悪いんだよって思ったんですが・・・。

<!-- リスト行のスタイル -->
<Style TargetType="ListViewItem" x:Key="ListViewItemStyle">
    <Setter Property="Background" Value="{Binding Converter={StaticResource rowColorConverter}}"/>
</Style>

上のように「XPath=.」を削除すると、意図したとおり XmlNode 型で渡されるようになりました。なんか納得いかないですが・・・。

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/2182

コメント

おはよう
ございます。

WPFをやっている関係でいつも何気にお世話になっております。
ありがとうございます。
ご相談があり書込みさせて頂きます。

ListViewの1つのセルの色をコードから変えたいのですが
自分なりに色々調べても行単位での設定は見つかるのですが
セル単位で操作する方法がわからないのです。

listView1.Items[1].SubItems[1].BackColor = Color.Azure;

このような感じでできるものかと思っていたのですが
できずに調べていたらこのブログに行き当たりました。

方法をご存知であれば教えて頂ければありがたいです。
よろしくお願いいたします。

こんにちは、またブログ覗かせていただきました。また、遊びに来ま~す。よろしくお願いします

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?