Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

DataGridで特定の列の値が重複してる行だけ色を変えたい

$
0
0

という問題が出されました。 うんうんと頭をひねった結果こうなりました…ちょっと全ループしてるのがダサい。ReactiveProperty 2.x前提です。

まず、表示するデータ。

using Reactive.Bindings;

namespace DupItemColorApp
{
    publicclass PersonViewModel
    {
        public ReactiveProperty<string> Name { get; private set; }
        public ReactiveProperty<int> Age { get; private set; }

        public ReactiveProperty<string> BackgroundColor { get; private set; }

        public PersonViewModel()
        {
            this.Name = new ReactiveProperty<string>();
            this.Age = new ReactiveProperty<int>();
            this.BackgroundColor = new ReactiveProperty<string>("White");
        }

        publicstatic PersonViewModel Create(string name, int age)
        {
            var result = new PersonViewModel();
            result.Name.Value = name;
            result.Age.Value = age;
            return result;
        }

    }
}

こいつのBackgroundColorをいじってDataGridのRowの色を変えるつもりです。

プロパティの変更と要素の変更時に全走査!ダサい…もっといい方法募集中。一応連続での値の変更なんかに対応するためにThrottle入れて緩和してる。

using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;

namespace DupItemColorApp
{
    publicclass MainWindowViewModel
    {
        privatestaticreadonlystring[] Names = new[]
        {
            "hoge",
            "fuga",
            "piyo",
            "foo",
            "bar",
            "bazz",
            "fizz",
        };
        
        privatereadonly ObservableCollection<PersonViewModel> people = new ObservableCollection<PersonViewModel>();
        public ReadOnlyReactiveCollection<PersonViewModel> People { get; private set; }

        public ReactiveCommand AddCommand { get; private set; }

        public MainWindowViewModel()
        {
            this.People = this.people.ToReadOnlyReactiveCollection();
            this.People.ObserveElementObservableProperty(x => x.Name)
                .Throttle(TimeSpan.FromMilliseconds(500))
                .Subscribe(x =>
                {
                    Console.WriteLine("Name changed.");
                    foreach (var item inthis.People.ToArray())
                    {
                        item.BackgroundColor.Value = "White";
                    }
                    this.ChangeBackgroundColor();
                });
            this.People.CollectionChangedAsObservable()
                .Throttle(TimeSpan.FromMilliseconds(500))
                .Subscribe(_ => this.ChangeBackgroundColor());

            this.AddCommand = new ReactiveCommand();
            this.AddCommand.Subscribe(_ =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    var name = Names.OrderBy(x => Guid.NewGuid()).First();
                    this.people.Add(PersonViewModel.Create(name, 0));
                }
            });
        }

        privatevoid ChangeBackgroundColor()
        {
            Debug.WriteLine("ChangeBackgroundColor called.");
            foreach (var item inthis.People.ToArray().GroupBy(x => x.Name.Value).Where(x => x.Count() > 1).SelectMany(x => x))
            {
                item.BackgroundColor.Value = "Red";
            }
        }
    }
}

んで、XAML。これはバインドしてるだけ。

<Window x:Class="DupItemColorApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:DupItemColorApp"mc:Ignorable="d"Title="MainWindow"Height="350"Width="525"><Window.DataContext><local:MainWindowViewModel /></Window.DataContext><Grid><Grid.RowDefinitions><RowDefinition Height="Auto" /><RowDefinition /></Grid.RowDefinitions><Menu><MenuItem Header="Add"Command="{Binding AddCommand}" /></Menu><DataGrid Grid.Row="1"ItemsSource="{Binding People}"AutoGenerateColumns="False"UseLayoutRounding="True"><DataGrid.RowStyle><Style TargetType="DataGridRow"><Setter Property="Background"Value="{Binding BackgroundColor.Value}" /></Style></DataGrid.RowStyle><DataGrid.Columns><DataGridTextColumn Header="Name"Binding="{Binding Name.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /><DataGridTextColumn Header="Age"Binding="{Binding Age.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /></DataGrid.Columns></DataGrid></Grid></Window>

Viewing all articles
Browse latest Browse all 1387

Trending Articles