yeah69 / bff.datavirtualizingcollection Goto Github PK
View Code? Open in Web Editor NEWThis is an approach to data virtualizing collections intended to be used in WPF projects.
License: The Unlicense
This is an approach to data virtualizing collections intended to be used in WPF projects.
License: The Unlicense
Hello,
Any plans to implement Add/Remove any time soon?
Thanks.
I cannot make heads or tails of what's going on here.
the sample is so full of layers of abstraction, I can't keep it all in my head at once.
all i want is to be able to get data virtualization over my observable collection.. why is this so confusing to do?
I'm so lost. I see the example and my brain sees:
your hello world example looks like it only works for some huge list of ints, is that whats going on??
Whats happening?
look, I know that's all probably not the most accurate of assessments of the work you're doing, I can tell that once I have any clue how it's getting any of this accomplished I'll be really happy with it, but please.. please... for the love of all that is good and right and holy.. have mercy on the slow ones among us..
please make an example of taking an ObservableCollection() where T is some sort of class with like.. an ID property or something.. and then show how you go from your datagrid looking at that, to your datagrid using your Data Virtualized collectionview instead.
please as straightforward as possible.
like I'm five.
and not a smart five year old either, like.. one you know won't get invited to parties when their older..
DataVirtualizingCollectionBuilder
.Build<DetailModel>
(
100,
_notificationScheduler,
_defaultScheduler
)
.NonPreloading()
.Hoarding()
.TaskBasedFetchers((offset, count, CancellationToken cancellationToken) => , ( CancellationToken cancellationToken) => )
and Add method CancelRequest{Async}
This is my current config:
ThrottledLifoPageRequests().AsyncIndexAccess((a, b) => {
return new T();
});
Question 1: It all works beautifully when used in a Grid, but what do I do if I need to actually grab the data? Use case: I want all items of the current collection to be processed in some way. If I just loop through all the items, I end up with a lot that are just filled with the placeholder null values. Is there a way to force grab all items? This is kind of the opposite of what this is meant to do, but it would be useful. However I could workaround this by just doing the fetching directly instead.
Question 2: Near the start of the DataGrid I'm able to select multiple rows, but as I get a bit into the dataset, whenever I select multiple rows, they stay selected for a short time but then immediately deselect again on their own. I did read the notes in https://github.com/Yeah69/BFF.DataVirtualizingCollection/wiki/Issue-of-Refreshes-while-selecting-items and I think this is probably related but I'm not sure what to do here. Selecting a single item works fine no matter where. And I'm not even trying to select items across multiple scrollings, just from the visible items. For fun I tried binding the SelectedIndex thing but it didn't do much.
This may be a stupid question and out of the scope of this project, but let's say I bind this to a DataGrid and I use the collection to fetch data from an SQLite database.
What happens if I click on the sort columns in WPF? Ideally I would just catch that (so it doesn't try to manually request & sort millions of entries), modify the SELECT query, invalidate all the data in the collection, and then ask it to repopulate as it sees fit.
Do you have a solution in mind for this kind of situation?
#region
using System;
using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using BFF.DataVirtualizingCollection.DataVirtualizingCollection;
#endregion
namespace ConsoleApp11
{
internal static class Program
{
public static int Version = 1;
private const int NumberItem = 5;
private static readonly TimeSpan Delay = TimeSpan.FromSeconds(1);
private static readonly TimeSpan EpsilonDelay = Delay / 10;
private static TestAsyncEnumerable testAsyncEnumerable;
private static IDataVirtualizingCollection<int> dataVirtualizingCollection;
private static async Task Main()
{
testAsyncEnumerable = new TestAsyncEnumerable(NumberItem, Delay);
dataVirtualizingCollection = DataVirtualizingCollectionBuilder.Build<int>
(
10,
new TaskPoolScheduler(Task.Factory)
)
.NonPreloading()
.Hoarding()
.AsyncEnumerableBasedFetchers(PageFetcher, CountFetcher)
.AsyncIndexAccess((_, _) => -2);
await Task.Delay(EpsilonDelay);
//problem not show CountFetcher cancel
dataVirtualizingCollection.Reset();
Version++;
await Task.Delay(Delay + EpsilonDelay);
var dataVirtualizing = dataVirtualizingCollection[0];
await Task.Delay(2 * Delay + EpsilonDelay);
//problem not show PageFetcher cancel
Version++;
dataVirtualizingCollection.Reset();
//problem not run PageFetcher version 3
dataVirtualizing = dataVirtualizingCollection[0];
Console.WriteLine("End");
Console.ReadKey();
}
private static async Task<int> CountFetcher(CancellationToken cancellationToken)
{
var version = Version;
try
{
Console.WriteLine($"{nameof(CountFetcher)} begin {nameof(Version)}={version}");
await Task.Delay(Delay, cancellationToken);
Console.WriteLine($"{nameof(CountFetcher)} end {nameof(Version)}={version}");
return NumberItem;
}
catch (OperationCanceledException)
{
Console.WriteLine($"{nameof(CountFetcher)} cancel {nameof(Version)}={version}");
throw;
}
}
private static async IAsyncEnumerable<int> PageFetcher
(
int offset,
int count,
[EnumeratorCancellation] CancellationToken cancellationToken
)
{
var version = Version;
Console.WriteLine($"{nameof(PageFetcher)} begin {nameof(Version)}={version}");
await foreach (var item in testAsyncEnumerable.WithCancellation(cancellationToken))
{
yield return item;
}
Console.WriteLine($"{nameof(PageFetcher)} end {nameof(Version)}={version}");
}
}
public class TestAsyncEnumerable : IAsyncEnumerable<int>
{
private readonly int _number;
private readonly TimeSpan _delay;
public TestAsyncEnumerable(int number, TimeSpan delay)
{
_number = number;
_delay = delay;
}
public IAsyncEnumerator<int> GetAsyncEnumerator
(
CancellationToken cancellationToken
) => new TestAsyncEnumerator(_number, _delay, Program.Version, cancellationToken);
}
public class TestAsyncEnumerator : IAsyncEnumerator<int>
{
private readonly int _number;
private readonly TimeSpan _timeSpan;
private readonly int _version;
private readonly CancellationToken _cancellationToken;
public TestAsyncEnumerator(int number, TimeSpan timeSpan, int version, CancellationToken cancellationToken)
{
_number = number;
_timeSpan = timeSpan;
_version = version;
_cancellationToken = cancellationToken;
}
public int Current { get; private set; } = -1;
public ValueTask DisposeAsync()
{
Console.WriteLine($"{nameof(DisposeAsync)} {nameof(Version)}={_version}");
return default;
}
public async ValueTask<bool> MoveNextAsync()
{
try
{
Console.WriteLine($"before {nameof(MoveNextAsync)} {nameof(Current)} {Current} {nameof(Version)}={_version}");
await Task.Delay(_timeSpan, _cancellationToken);
var current = Current + 1;
if (current >= _number)
{
Console.WriteLine($"end {nameof(MoveNextAsync)} {nameof(Current)} {Current} {nameof(Version)}={_version}");
return false;
}
Current = current;
Console.WriteLine($"after {nameof(MoveNextAsync)} {nameof(Current)} {Current} {nameof(Version)}={_version}");
return true;
}
catch (OperationCanceledException)
{
Console.WriteLine($"{nameof(TestAsyncEnumerator)} is canceled {nameof(Version)}={_version}");
throw;
}
}
}
}
Hi,
this is not an issue but a sample request .
that would be great if you can demonstrate this library with other data controls than the datagrid .
for example :
i would love to see a sample of a datavirtualized listbox with multiples columns
something like this : https://ibb.co/2kQVxvM
anyway thanks for the hard work .
I like your implementation of Virtualizing Data, but, for a my project, it's not possible to use the current implementation because does not discharge the pages when are not used!
There are any plan to improve the current Page-Holding mechanism with a new 'strategy' that reuse memory?
Add override methods
public IAsyncOnlyIndexAccessBehaviorCollectionBuilder<TItem, TVirtualizationKind> TaskBasedFetchers(
Func<int, int, CancellationToken, IAsyncEnumerable<TItem>> pageFetcherAsync,
Func<CancellationToken, Task<int>> countFetcherAsync)
{
}
public IIndexAccessBehaviorCollectionBuilder<TItem, TVirtualizationKind> NonTaskBasedFetchers(
Func<int, int, IEnumerableT<Item>> pageFetcher,
Func<int> countFetcher)
{
}
Hi, I went back to try this library and I immediately have a new question.
I have a database that is updated continuously (the records increase every second).
I need to show these values in a ListView but I want to manage the data, if it's possible, with your library.
The data are shown starting from the newer to the older, for this reason I have a timer that check the DB for the new data and load only these in memory, after add these new items to the collection in binding with the ListView (insert the data at the 0 position).
Is it possible to manage these collection with your library?
If the answer is yes, how I can manage the data (update the count, update the selected index/offset)?
I've noticed that foreach is not working as expected. Do I miss something?
How to reproduce:
Add the following code in BFF.DataVirtualizingCollection.Sample in MainWindow.xaml.cs at the end of the constructor:
Debug.WriteLine(MillionNumbers.Count());
foreach (var item in MillionNumbers)
{
Debug.WriteLine(item);
}
The Debug.WriteLine(MillionNumbers.Count());
shows correctly 1000000 but it is not entering foreach loop. It looks like GetEnumerator()
in DataVirtualizingCollectionBase.cs
is giving null.
Please advice.
There is a problem in wpf, with fast scrolling, many pages are requested and until all of them are received, the data is not displayed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.