我正在测试Rx.net或一般的反应式扩展,因此在我的WPF应用程序中,我有一个数据网格,其中包含多达一百万行。
我的目标是根据文本框输入和颜色选择器的颜色选择提供动态行背景颜色设置(我在这里使用https://github.com/PropertyTools/PropertyTools颜色选择器)。
该应用程序的当前行为可以在以下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>