XmlDataProvider にバインドした ListView で、データに応じて行の背景色を変更する
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;
このような感じでできるものかと思っていたのですが
できずに調べていたらこのブログに行き当たりました。
方法をご存知であれば教えて頂ければありがたいです。
よろしくお願いいたします。
こんにちは、またブログ覗かせていただきました。また、遊びに来ま~す。よろしくお願いします