Coder Social home page Coder Social logo

yeah69 / bff.datavirtualizingcollection Goto Github PK

View Code? Open in Web Editor NEW
43.0 43.0 5.0 6.22 MB

This is an approach to data virtualizing collections intended to be used in WPF projects.

License: The Unlicense

C# 100.00%
csharp data-virtualization wpf

bff.datavirtualizingcollection's People

Contributors

kronic avatar yeah69 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bff.datavirtualizingcollection's Issues

sample extremely complicated.. DataVirtualization for dummies please?

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.
image

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:
image

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..
image

Add CancelationToken.

DataVirtualizingCollectionBuilder
				.Build<DetailModel>
				(
					100,
					_notificationScheduler,
					_defaultScheduler
				)
				.NonPreloading()
				.Hoarding()
				.TaskBasedFetchers((offset, count, CancellationToken cancellationToken) => , ( CancellationToken cancellationToken) => )

and Add method CancelRequest{Async}

Force sync'd access and issue with selecting multiple items

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.

Sorting

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?

Reset method problem

#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;
			}
		}
	}
}

sample request

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 .

[Question] Any plan to improve the Page-Holding?

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 TaskBasedFetchers

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)
{
}

[Question] How to manage data that is continuously increasing?

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)?

foreach is not working for me

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.

Slow

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.

  1. I suggest displaying data not based on queue, but based on stack.
  2. Add custom pause for new page request. If the page has changed at the time of pause, then we do not request it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.