none
wpf toolkit Datagrid 行の色変更 RRS feed

  • 質問

  • はじめまして。WPF勉強中のkmo3と申します

    wpf toolkit Datagridを使用しDataBindingにてデータ表示を行っています。
    ボタン押下でデータに変更を加え、その内容によりコンバータで色データに変換し、各行の表示色を変えるということをしています。
    データ自体はバインディングによりDataGridに反映されるのですが、表示色が変わらず困っています。
    Datagrid領域をスクロールバーにてスクロールすると行の表示色が変わるので再描画されていないのかと考えています。
    Repaint,Refreshなどで調べたのですが、方法がわからず困っております。
    強制的に再描画することは出来るのでしょうか?

    よろしくお願い致します。
    2009年9月2日 13:17

回答

  • この場合は Converter の入力は RowDataList の一行のデータになります。
    複数のデータの状況を見て色を決めるのであれば RowDataList の INotifyCollectionChanged.CollectionChanged が必要です。
     RowDataList の INotifyCollectionChanged.CollectionChanged は発生していますでしょうか?

    もし、単一データで色を決めるのであれば RowDataList の データの色を変える部分のプロパティを うつせみ さんのように指定する必要があり、Converter の入力を RowDataList の一行から 色を変える部分のプロパティに変更する必要があります。
    つまり、うつせみ さんのようにするには Converter のプログラムも変更する必要があります。


    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    • 回答としてマーク kmo3 2009年9月3日 12:48
    2009年9月3日 6:17

すべての返信

  • >その内容によりコンバータで色データに変換し、各行の表示色を変える
    色データに変換する元データの PropertyChanged イベントは発生しているでしょうか?

    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月2日 13:43
  • 元データのPropertyChanged イベントは発生しています。
    元データもDataGridに表示しているのですが、その部分に関しては期待した値に書き換わっております。
    色に関してだけ、Datagrid領域をスクロールしてやらないと変わらない状況です。一度、対象の行を隠して再度出すというスクロール操作です。

    よろしくお願いします。

    2009年9月2日 15:16
  • Binding している部分だけでもコードを見せてもらえませんか?

    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月2日 15:37
  • DataTable等にデータ変更が反映されてれば色は強制的に再描画せずとも変わるとは思うんですが。
    現在使っている分一部だけ抜き出してみました。

    XAML側
    <dg:DataGrid Name="dataGrid1" ItemsSource="{Binding}">
        <dg:DataGrid.ItemContainerStyle>
            <Setter Property="Background" Value="{Binding Check, Converter={StaticResource rowColorConverter}}"/>
        </dg:DataGrid.ItemContainerStyle>
    </dg:DataGrid>
    Converter側
    using System;
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows.Media;
    
    namespace WPFApp01.Converters {
        public class RowColorConverter : IValueConverter {
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
                string stringValue = System.Convert.ToString(value);
    
                if (stringValue == "-2") {
                    return new LinearGradientBrush(Color.FromArgb(255, 150, 176, 162), Color.FromArgb(255, 150, 176, 162), 45);
                }
                if (stringValue == "0") {
                    return new LinearGradientBrush(Colors.Pink, Colors.Pink, 45);
                }
                return new LinearGradientBrush(Colors.White, Colors.White, 45);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
                throw new NotImplementedException();
            }
        }
    }
    複数色に条件で切り替えてるんで見にくかったらごめんなさい。


    2009年9月2日 23:59
  • うつせみ様

    情報ありがとうございます。

    やはり、再描画しなくても変わるはずですか・・。
    もう少し調べてみます。

    ちなみに、強制的に再描画をさせるってことは出来るのでしょうか?
    メソッドにないか調べたのですが、見当たりませんでした。

    よろしくお願い致します。
    2009年9月3日 2:42
  • えムナウ 様

    >Binding している部分だけでもコードを見せてもらえませんか?

    <WPFToolkit:DataGrid AutoGenerateColumns="True" Margin="1,1,0,0" Name="ReportData" ItemsSource="{Binding Path=RowDataList}" HorizontalContentAlignment="Left" HorizontalAlignment="Right" Width="719" Height="557" VerticalAlignment="Bottom" HeadersVisibility="All" Background="White" BorderBrush="Black" SelectedIndex="0" TabIndex="0">
        <WPFToolkit:DataGrid.ItemContainerStyle>
            <Style TargetType="WPFToolkit:DataGridRow">
                <Setter Property="Background" Value="{Binding Converter={StaticResource Converter1}}"/>
            </Style>
        </WPFToolkit:DataGrid.ItemContainerStyle>
    </WPFToolkit:DataGrid>

    コンバータでは、数値データを判定し、Brushes.Redなどをreturnしています。

    よろしくお願いします。
    2009年9月3日 2:43
  • 気になった点をいくつか。(関係ないかもしれません。試していただけると^^)

    <Setter Property="Background" Value="{Binding Converter={StaticResource Converter1}}"/>
    Binding Converter={StaticResource Converter1}部分の記述
    Binding AAA, Converter={StaticResource Converter1}って感じで。
    抜き出す際に消しただけですよね?


        <WPFToolkit:DataGrid.ItemContainerStyle>
            <Style TargetType="WPFToolkit:DataGridRow">
                <Setter Property="Background" Value="{Binding Converter={StaticResource Converter1}}"/>
            </Style>
        </WPFToolkit:DataGrid.ItemContainerStyle>

        <WPFToolkit:DataGrid.ItemContainerStyle>
             <Setter Property="Background" Value="{Binding AAA, Converter={StaticResource Converter1}}"/>
        </WPFToolkit:DataGrid.ItemContainerStyle>
    に変えてみたらどうでしょう?

    試してないのでハズしてるかもです。
    2009年9月3日 4:53
  • うつせみ 様
    情報ありがとうございます。
    試してみたのですが・・わからない部分があるので質問させてください。

    質問なのですが、AAAにあたる部分にはコンバート前のデータが入っているプロパティを入れれば良いのでしょうか?
    それで良いのでしたら試したところ画面初期表示で色を付けていた部分に関しても色がつかなくなってしまいました。

    よろしくお願いします。
    2009年9月3日 5:51
  • この場合は Converter の入力は RowDataList の一行のデータになります。
    複数のデータの状況を見て色を決めるのであれば RowDataList の INotifyCollectionChanged.CollectionChanged が必要です。
     RowDataList の INotifyCollectionChanged.CollectionChanged は発生していますでしょうか?

    もし、単一データで色を決めるのであれば RowDataList の データの色を変える部分のプロパティを うつせみ さんのように指定する必要があり、Converter の入力を RowDataList の一行から 色を変える部分のプロパティに変更する必要があります。
    つまり、うつせみ さんのようにするには Converter のプログラムも変更する必要があります。


    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    • 回答としてマーク kmo3 2009年9月3日 12:48
    2009年9月3日 6:17
  • kmo3 さん
    うつせみです。ハズした回答をしてました。
    <Style TargetType="WPFToolkit:DataGridRow">がいらないとか回答してました。

    とりあえずテストで作ってみました。
    どこかにファイルをアップすれば早いのですが。。。

    XAML
    <Window x:Class="WpfApplication01.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window1" Height="300" Width="300"
            xmlns:WPFToolkit="http://schemas.microsoft.com/wpf/2008/toolkit">
        <Grid>
            <WPFToolkit:DataGrid Name="dataGrid1"
                                 ItemsSource="{Binding}"
                                 AutoGenerateColumns="False">
                <WPFToolkit:DataGrid.ItemContainerStyle>
                    <Style TargetType="WPFToolkit:DataGridRow">
                        <Setter Property="Background" Value="{Binding Check, Converter={StaticResource rowColorConverter}}"/>
                    </Style>
                </WPFToolkit:DataGrid.ItemContainerStyle>
    
                <WPFToolkit:DataGrid.Columns>
                    <WPFToolkit:DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" />
                    <WPFToolkit:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" />
                    <WPFToolkit:DataGridTextColumn Header="Address" Binding="{Binding Path=Address}" />
                    <WPFToolkit:DataGridTextColumn Header="Check" Binding="{Binding Path=Check}" />
                </WPFToolkit:DataGrid.Columns>
            </WPFToolkit:DataGrid>
        </Grid>
    </Window>
    コードビハインド(C#)
    using System.Linq;
    using System.Windows;
    
    namespace WpfApplication01 {
        public partial class Window1 {
            public Window1() {
                InitializeComponent();
    
                DataContext = Enumerable.Range(1, 20).Select(i =>
                    new Person {
                        ID = i,
                        Name = "Test" + i.ToString(("00")),
                        Address = "Address" + i.ToString("00"),
                        Check = 0
                    }).ToList();
            }
        }
    }
    Person.cs
    namespace WpfApplication01 {
        public class Person {
            public int ID { get; set; }
            public string Name { get; set; }
            public string Address { get; set; }
            public int Check { get; set; }
        }
    }
    RowColorConverter.cs
    using System;
    using System.Globalization;
    using System.Windows.Data;
    using System.Windows.Media;
    
    
    namespace WpfApplication01 {
        public class RowColorConverter : IValueConverter {
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
                string stringValue = System.Convert.ToString(value);
    
                if (stringValue == "1") {
                    return new LinearGradientBrush(Colors.Pink, Colors.Pink, 45);
                }
                return new LinearGradientBrush(Colors.White, Colors.White, 45);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
                throw new NotImplementedException();
            }
        }
    }
    
    App.xaml
    <Application x:Class="WpfApplication01.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="Window1.xaml">
        <Application.Resources>
             <ResourceDictionary Source="ConvertersDictionary.xaml" />
        </Application.Resources>
    </Application>
    
    2009年9月3日 6:25
  • えムナウ様
    うつせみ様

    教えて頂き、ありがとうございます。
    色が変更される様になりました。本当にありがとうございます。

    ただ、一つ良くわからないのですが、

    >Converter の入力を RowDataList の一行から 色を変える部分のプロパティに変更する必要があります。
    >つまり、うつせみ さんのようにするには Converter のプログラムも変更する必要があります。

    上記を行った所、動作したのですが、
    Converterの入力に RowDataList の一行を渡して、その一行の中の1プロパティを Converterプログラムで判定し、Brushesを返した場合と何が違うのでしょうか?
    Brushesを返し、Property="Background"に入っているなら同じ結果になってもいいように考えているのですが。
    スクロールすると期待通りに表示されるのProperty="Background"に伝わっていると考えてしまいます。
    動作はしたのですが、どうもそのあたりが気になります。

    よろしくお願いします。

    2009年9月3日 8:32
  • >Converterの入力に RowDataList の一行を渡して、その一行の中の1プロパティを Converterプログラムで判定し、Brushesを返した場合と何が違うのでしょうか?
    WPF が再評価するトリガが PropertyChanged と CollectionChanged の違いになります。

    RowDataList の一行を渡すと、 RowDataList に対して CollectionChanged が必要になります。
    一行の中の1プロパティを渡すと、そのプロパティが変化した PropertyChanged だけでいいことになります。

    つまりBindしたデータ(RowDataList の一行=CollectionChanged /一行の中の1プロパティ=PropertyChanged )が変化したことをWPFに教える必要があります。


    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月3日 8:52
  • えムナウ様

    RowDataListをObservableCollection<T>で定義しているのですが、ObservableCollection<T>を使えばコレクションに変更があった場合、
    CollectionChangedイベントが発生するという認識です。
    なので、特に何もしないで良いと考えていましたが、この考えは間違っているのでしょうか?

    よろしくお願いします。

    2009年9月3日 9:36
  • コレクションに変更があった場合はコレクションに追加や削除があった場合です。
    コレクションの1データの1プロパティに変更があった場合に発生するものではありません。

    >ObservableCollection<T>を使えばコレクションに変更があった場合、CollectionChangedイベントが発生するという認識です。
    つまり ObservableCollection<T> の Tのクラス内の PropertyChanged を ObservableCollection<T> の CollectionChanged にエスカレーションする仕組みが別途使う側で必要です。

    えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
    2009年9月3日 9:43
  • えムナウ様

    ありがとうございます。
    ようやく理解しました。納得しました。
    ObservableCollection<T> の CollectionChanged にエスカレーションする仕組みについては勉強が必要ですが・・。

    よろしくお願いします。
    2009年9月3日 9:54
  • えムナウ様

    ありがとうございます。
    ようやく理解しました。納得しました。
    ObservableCollection<T> の CollectionChanged にエスカレーションする仕組みについては勉強が必要ですが・・。

    よろしくお願いします。
    2009年9月3日 9:55