Обработчик события CollectionChanged

227
31 января 2018, 11:28

Имеется сторонний контрол, который биндится к коллекции, имплементирующей CollectionChagned. Проблема в том что коллекция обновляется слишком часто, из-за чего при отрисовке подвисает UI.

Какими путями можно добиться "прореживания" обработки события CollectionChagned.

P.S. коллекция тоже от стороннего контрола, я не могу самостоятельно вызывать OnCollectionChanged.

Answer 1

Если коллекция небольшая, то можно периодически делать ее дамп и выводить в GUI именно его вместо исходной коллекции.

Я набросал такой пример: исходная коллекция заполняется по таймеру каждые 20 мс, дамп создается каждые 100 мс:

class MainVm : Vm
{
    public ICommand StartUpdatingCommand { get; }
    public ICommand StopUpdatingCommand { get; }
    CancellationTokenSource cancellationTokenSource;
    public ObservableCollection<int> Collection { get; }
    IEnumerable<int> collectionDump;
    public IEnumerable<int> CollectionDump
    {
        get => collectionDump;
        set => Set(ref collectionDump, value, nameof(CollectionDump));
    }
    public MainVm()
    {
        StartUpdatingCommand = new DelegateCommand(_ => StartUpdating());
        StopUpdatingCommand = new DelegateCommand(_ => StopUpdating());
        Collection = new ObservableCollection<int>();
        CollectionDump = Collection.ToArray();
        var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(20) };
        timer.Tick += delegate { Collection.Add(10); Collection.Add(20); if (Collection.Count > 100) Collection.Clear(); };
        timer.Start();
    }
    private async void StartUpdating()
    {
        if (cancellationTokenSource != null) return;
        cancellationTokenSource = new CancellationTokenSource();
        try
        {
            while (!cancellationTokenSource.IsCancellationRequested)
            {
                CollectionDump = Collection.ToArray();
                await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationTokenSource.Token);
            }
        }
        catch (OperationCanceledException) { }
        finally
        {
            cancellationTokenSource = null;
        }
    }
    private void StopUpdating()
    {
        cancellationTokenSource?.Cancel();
    }
}

Разметка содержимого окна:

<Grid Margin="5">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ListBox ItemsSource="{Binding CollectionDump}"/>
    <UniformGrid Grid.Row="1" Margin="0,5,0,0"
                 HorizontalAlignment="Center" Rows="1">
        <UniformGrid.Resources>
            <Style TargetType="Button">
                <Setter Property="Padding" Value="10,2"/>
                <Setter Property="Margin" Value="2.5"/>
            </Style>
        </UniformGrid.Resources>
        <Button Content="Start updating" Command="{Binding StartUpdatingCommand}"/>
        <Button Content="Stop updating" Command="{Binding StopUpdatingCommand}"/>
    </UniformGrid>
</Grid>

Обратите внимание, привязка именно к CollectionDump

READ ALSO
Перенос данных для разных СУБД в EntityFramework Migrations

Перенос данных для разных СУБД в EntityFramework Migrations

Есть приложение, использующее в качестве ORM EntityFrameworkНужно к этому приложению прикрутить миграцию БД

214
Экспорт данных из файла Excel в DataGridView

Экспорт данных из файла Excel в DataGridView

Нашел код для загрузки данных Excel в таблицу DataGridView:

251
Эффективное хранение списка файлов

Эффективное хранение списка файлов

Допустим, есть N-ое кол-во директорий, в каждой директории хранится M файлов с уникальными именами, которые не пересекаются с файлами из других...

182
Запустится ли приложение?

Запустится ли приложение?

Запустится ли приложение, если скомпилировано подNet Framework 3

293