Как установить цвет фона строки datagrid в зависимости от условия с помощью rx. net? - PullRequest
0 голосов
/ 01 августа 2020

Я тестирую Rx. net или вообще реактивные расширения, поэтому в моем приложении WPF у меня есть сетка данных, содержащая до 1 миллиона строк.

Моя цель - предоставить настройка цвета фона строки Dynami c на основе ввода текстового поля и выбора цвета из палитры цветов (здесь я использую https://github.com/PropertyTools/PropertyTools Color Picker).

Текущее поведение приложения можно увидеть в этом gif:

поведение приложения

Соответствующая часть кода, которая выполняет работу, выглядит следующим образом:

 public class MainViewModel : ReactiveObject
    {
        [Reactive] public string SearchPhrase { get; set; } = "0";

        [Reactive] public Color ColorPickerSelectedColor { get; set; }

        private readonly ReadOnlyObservableCollection<DataGridViewModel> _itemsBinding;
        private IObservable<IChangeSet<DataGridViewModel>> _dataListObservable;

        public ReadOnlyObservableCollection<DataGridViewModel> TargetCollection => _itemsBinding;

        public MainViewModel(SourceList<DataGridViewModel> _dataList)
        {

            AddSomeRandomData(_dataList);

            _dataListObservable = _dataList.Connect();

            _dataListObservable.ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out _itemsBinding)
                .DisposeMany()
                .Subscribe();

            this.WhenAnyValue(p1 => p1.ColorPickerSelectedColor, p2 => p2.SearchPhrase)
                .Throttle(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
                .ObserveOn(RxApp.TaskpoolScheduler)
                .Subscribe(_ =>
                {
                    _dataListObservable.AsObservableList().Items.ForEach(item => {
                        item.BackgroundColor = item.Id.Equals(SearchPhrase, StringComparison.OrdinalIgnoreCase) ? ColorPickerSelectedColor : default;
                    });
                });

        }

        private void AddSomeRandomData(SourceList<DataGridViewModel> _dataList)
        {
            var random = new Random();
            for (int i = 0; i < 1e6; i++)
            {

                var buffer = new byte[random.Next(1, 80)];

                random.NextBytes(buffer);
                string hexData = BitConverter.ToString(buffer);

                int randomId = random.Next(1, 10);

                var dataGridViewModel = new DataGridViewModel
                {
                    TimeStamp = DateTime.Now.ToString("HH:mm:ss.ffffff"),
                    Id = randomId.ToString(),
                    HexData = hexData,
                    BackgroundColor = ColorPickerSelectedColor
                };

                _dataList.Add(dataGridViewModel);
            }
        }
    }

Хотя приложение работает, как ожидалось, я думаю, что я реализовал настройку цвета фона, эта часть:

this.WhenAnyValue(p1 => p1.ColorPickerSelectedColor, p2 => p2.SearchPhrase)
                .Throttle(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
                .ObserveOn(RxApp.TaskpoolScheduler)
                .Subscribe(_ =>
                {
                    _dataListObservable.AsObservableList().Items.ForEach(item => {
                        item.BackgroundColor = item.Id.Equals(SearchPhrase, StringComparison.OrdinalIgnoreCase) ? ColorPickerSelectedColor : default;
                    });
                });

немного не так.

Может кто-нибудь показать мне лучший способ сделать это?

Части xaml:

DataGridControl

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:reactivedatagridtest="clr-namespace:ReactiveDataGridTest"
                    x:Class="ReactiveDataGridTest.Ressources.DataGridControl">
    <DataGrid ItemsSource="{Binding TargetCollection}" 
              x:Key="MainTracingDataGrid"
            x:Name="TracingDataGrid"
            ScrollViewer.ScrollChanged="TracingDataGrid_ScrollChanged"
            EnableRowVirtualization="True"
            RowHeight="40"
            AutoGenerateColumns="False">
        <DataGrid.Resources>
            <reactivedatagridtest:ColorToSolidColorBrushValueConverter x:Key="ColorToSolidColorBrush_ValueConverter"/>
            <Style TargetType="DataGridRow">
                <Setter Property="Background" Value="{Binding BackgroundColor, Converter={StaticResource ColorToSolidColorBrush_ValueConverter}}"/>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Timestamp" Binding="{Binding TimeStamp}"/>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Data" Binding="{Binding HexData}"/>
        </DataGrid.Columns>
    </DataGrid>
</ResourceDictionary>

MainWindow

<Window x:Class="ReactiveDataGridTest.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:ReactiveDataGridTest" 
        xmlns:p="clr-namespace:PropertyTools.Wpf;assembly=PropertyTools.Wpf"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Ressources/DataGridControl.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ToolBar Grid.Row="0">
            <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                <materialDesign:PackIcon Kind="Search"/>
                <TextBox Width="150" Text="{Binding SearchPhrase, UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
            <Separator/>
            <p:ColorPicker SelectedColor="{Binding ColorPickerSelectedColor}" />
        </ToolBar>
        <ContentControl Content="{StaticResource MainTracingDataGrid}" Grid.Row="1"/>
    </Grid>
</Window>
...