Skip to content

Commit

Permalink
Collections component (#123)
Browse files Browse the repository at this point in the history
* New Collections component

* Removing IncrementalLoadingCollection and AdvanctedCollectionView components

* Fix namespaces
  • Loading branch information
niels9001 authored Jul 11, 2023
1 parent 3decd11 commit be4577e
Show file tree
Hide file tree
Showing 42 changed files with 154 additions and 372 deletions.

This file was deleted.

149 changes: 0 additions & 149 deletions components/AdvancedCollectionView/samples/AdvancedCollectionView.md

This file was deleted.

File renamed without changes.
98 changes: 98 additions & 0 deletions components/Collections/samples/AdvancedCollectionView.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: AdvancedCollectionView
author: nmetulev
description: The AdvancedCollectionView is a collection view implementation that support filtering, sorting and incremental loading. It's meant to be used in a viewmodel.
keywords: AdvancedCollectionView, data, sorting, filtering
dev_langs:
- csharp
category: Helpers
subcategory: Data
discussion-id: 0
issue-id: 0
icon: Assets/AdvancedCollectionView.png
---

> [!Sample AdvancedCollectionViewSample]
## Usage

In your viewmodel instead of having a public [IEnumerable](/dotnet/core/api/system.collections.generic.ienumerable-1) of some sort to be bound to an eg. [Listview](/uwp/api/Windows.UI.Xaml.Controls.ListView), create a public AdvancedCollectionView and pass your list in the constructor to it. If you've done that you can use the many useful features it provides:

* sorting your list using the `SortDirection` helper: specify any number of property names to sort on with the direction desired
* filtering your list using a [Predicate](/dotnet/core/api/system.predicate-1): this will automatically filter your list only to the items that pass the check by the predicate provided
* deferring notifications using the `NotificationDeferrer` helper: with a convenient _using_ pattern you can increase performance while doing large-scale modifications in your list by waiting with updates until you've completed your work
* incremental loading: if your source collection supports the feature then AdvancedCollectionView will do as well (it simply forwards the calls)
* live shaping: when constructing the `AdvancedCollectionView` you may specify that the collection use live shaping. This means that the collection will re-filter or re-sort if there are changes to the sort properties or filter properties that are specified using `ObserveFilterProperty`

## Example

```csharp
using Microsoft.Toolkit.Uwp.UI;

// Grab a sample type
public class Person
{
public string Name { get; set; }
}

// Set up the original list with a few sample items
var oc = new ObservableCollection<Person>
{
new Person { Name = "Staff" },
new Person { Name = "42" },
new Person { Name = "Swan" },
new Person { Name = "Orchid" },
new Person { Name = "15" },
new Person { Name = "Flame" },
new Person { Name = "16" },
new Person { Name = "Arrow" },
new Person { Name = "Tempest" },
new Person { Name = "23" },
new Person { Name = "Pearl" },
new Person { Name = "Hydra" },
new Person { Name = "Lamp Post" },
new Person { Name = "4" },
new Person { Name = "Looking Glass" },
new Person { Name = "8" },
};

// Set up the AdvancedCollectionView with live shaping enabled to filter and sort the original list
var acv = new AdvancedCollectionView(oc, true);

// Let's filter out the integers
int nul;
acv.Filter = x => !int.TryParse(((Person)x).Name, out nul);

// And sort ascending by the property "Name"
acv.SortDescriptions.Add(new SortDescription("Name", SortDirection.Ascending));

// Let's add a Person to the observable collection
var person = new Person { Name = "Aardvark" };
oc.Add(person);

// Our added person is now at the top of the list, but if we rename this person, we can trigger a re-sort
person.Name = "Zaphod"; // Now a re-sort is triggered and person will be last in the list
// AdvancedCollectionView can be bound to anything that uses collections.
YourListView.ItemsSource = acv;
```

## Remarks

_What source can I use?_

It's not necessary to use an eg. [ObservableCollection](/dotnet/core/api/system.collections.objectmodel.observablecollection-1) to use the AdvancedCollectionView. It works as expected even when providing a simple [List](/dotnet/core/api/system.collections.generic.list-1) in the constructor.

_Any performance guidelines?_

If you're removing, modifying or inserting large amounts of items while having filtering and/or sorting set up, it's recommended that you use the `NotificationDeferrer` helper provided. It skips any performance heavy logic while it's in use, and automatically calls the `Refresh` method when disposed.

```csharp
using (acv.DeferRefresh())
{
for (var i = 0; i < 500; i++)
{
acv.Add(new Person { Name = "defer" });
}
} // acv.Refresh() gets called here
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Page x:Class="AdvancedCollectionViewExperiment.Samples.AdvancedCollectionViewSample"
<Page x:Class="CollectionsExperiment.Samples.AdvancedCollectionViewSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CommunityToolkit.WinUI"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

using CommunityToolkit.WinUI;

namespace AdvancedCollectionViewExperiment.Samples;
namespace CollectionsExperiment.Samples;

[ToolkitSample(id: nameof(AdvancedCollectionViewSample), "AdvancedCollectionView", description: $"A sample for showing how to create and use a {nameof(AdvancedCollectionView)}.")]
public sealed partial class AdvancedCollectionViewSample : Page
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
<PropertyGroup>
<ToolkitComponentName>IncrementalLoadingCollection</ToolkitComponentName>
<ToolkitComponentName>Collections</ToolkitComponentName>
</PropertyGroup>

<!-- Sets this up as a toolkit component's sample project -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,6 @@ icon: Assets/IncrementalLoadingCollection.png

[IncrementalLoadingCollection](/dotnet/api/microsoft.toolkit.uwp.incrementalloadingcollection-2) - An extension of [ObservableCollection](/dotnet/api/system.collections.objectmodel.observablecollection-1) such that its items are loaded only when needed.

## IncrementalLoadingCollection Properties

| Property | Type | Description |
| -- | -- | -- |
| CurrentPageIndex | int | Gets or sets a value indicating The zero-based index of the current items page |
| HasMoreItems | bool | Gets a value indicating whether the collection contains more items to retrieve |
| IsLoading | bool | Gets a value indicating whether new items are being loaded |
| ItemsPerPage | int | Gets a value indicating how many items that must be retrieved for each incremental call |
| OnEndLoading | [Action](/dotnet/api/system.action) | Gets or sets an Action that is called when a retrieval operation ends |
| OnError | Action\<Exception> | Gets or sets an Action that is called if an error occours during data retrieval. The actual Exception is passed as an argument |
| OnStartLoading | Action | Gets or sets an Action that is called when a retrieval operation begins |

## IncrementalLoadingCollection Methods

| Methods | Return Type | Description |
| -- | -- | -- |
| LoadDataAsync(CancellationToken) | Task<IEnumerable\<IType>> | Actually performs the incremental loading |
| LoadMoreItemsAsync(UInt32) | IAsyncOperation\<LoadMoreItemsResult> | Initializes incremental loading from the view |
| Refresh() | void | Clears the collection and resets the page index which triggers an automatic reload of the first page |
| RefreshAsync() | Task | Clears the collection and reloads data from the source |

## Example

`IIncrementalSource` allows to define the data source:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Page x:Class="IncrementalLoadingCollectionExperiment.Samples.IncrementalLoadingCollectionSample"
<Page x:Class="CollectionsExperiment.Samples.IncrementalLoadingCollectionSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CommunityToolkit.WinUI"
Expand Down
Loading

0 comments on commit be4577e

Please sign in to comment.