Skip to content

Commit

Permalink
Merge branch 'main' into tests/diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
Arlodotexe authored Nov 8, 2024
2 parents b588832 + c7c0f94 commit 2120f62
Show file tree
Hide file tree
Showing 23 changed files with 93 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ contact_links:
about: "The Windows Community Toolkit uses Uno Platform for cross-platform WinUI. See the Uno Platform repo for issues specific to running on non-Windows platforms:"
- name: Discord
url: https://aka.ms/wct/discord
about: "Join the UWP Discord Server and talk to us in the #community-toolkit channel."
about: "Join the Windows App Community Discord Server and talk to us in the #community-toolkit channel."
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
<RootNamespace>CommunityToolkit.WinUI.BehaviorsRns</RootNamespace>
<PackageReadmeFile>ReadMe.md</PackageReadmeFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<!-- Sets this up as a toolkit component's source project -->
Expand Down
61 changes: 7 additions & 54 deletions components/Collections/samples/AdvancedCollectionView.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
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, Collections
description: The AdvancedCollectionView is a collection view implementation that support filtering, sorting and incremental loading. It's meant to be used in a view or viewmodel.
keywords: AdvancedCollectionView, CollectionViewSource, data, sorting, filtering, Collections
dev_langs:
- csharp
category: Helpers
Expand All @@ -12,70 +12,23 @@ issue-id: 0
icon: Assets/AdvancedCollectionView.png
---

> [!Sample AdvancedCollectionViewSample]
## Usage

In your viewmodel instead of having a public [IEnumerable](https://learn.microsoft.com/dotnet/core/api/system.collections.generic.ienumerable-1) of some sort to be bound to an eg. [Listview](https://learn.microsoft.com/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:
In your view or viewmodel instead of having a public [IEnumerable](https://learn.microsoft.com/dotnet/core/api/system.collections.generic.ienumerable-1) of some sort to be bound to an eg. [Listview](https://learn.microsoft.com/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](https://learn.microsoft.com/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 CommunityToolkit.WinUI.Collections;

// Grab a sample type
public class Person
{
public string Name { get; set; }
}
The `AdvancedCollectionView` is a good replacement for WPF's `CollectionViewSource`.

// 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);
## Example

// 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
The following is a complete example of how to perform ...

// AdvancedCollectionView can be bound to anything that uses collections.
YourListView.ItemsSource = acv;
```
> [!Sample AdvancedCollectionViewSample]
## Remarks

Expand Down
15 changes: 9 additions & 6 deletions components/Collections/samples/AdvancedCollectionViewSample.xaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- 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. -->
<!-- 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="CollectionsExperiment.Samples.AdvancedCollectionViewSample"
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:local="using:AdvancedCollectionViewExperiment.Samples"
xmlns:local="using:CollectionsExperiment.Samples"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

Expand All @@ -17,8 +17,9 @@
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
</Style.Setters>
</Style>
<DataTemplate x:Key="PersonDataTemplate">
<TextBlock Text="{Binding Name}" />
<DataTemplate x:Key="EmployeeDataTemplate"
x:DataType="local:Employee">
<TextBlock Text="{x:Bind Name}" />
</DataTemplate>
</Page.Resources>
<Grid ColumnSpacing="12"
Expand Down Expand Up @@ -51,7 +52,8 @@
<Grid Grid.Row="2"
Style="{StaticResource CardStyle}">
<ListView x:Name="LeftList"
ItemTemplate="{StaticResource PersonDataTemplate}" />
ItemTemplate="{StaticResource EmployeeDataTemplate}"
ItemsSource="{x:Bind EmployeeCollection}" />
</Grid>
<TextBlock Grid.Row="1"
Grid.Column="1"
Expand All @@ -60,7 +62,8 @@
Grid.Column="1"
Style="{StaticResource CardStyle}">
<ListView x:Name="RightList"
ItemTemplate="{StaticResource PersonDataTemplate}" />
ItemTemplate="{StaticResource EmployeeDataTemplate}"
ItemsSource="{x:Bind CollectionView}" />
</Grid>
</Grid>
</Page>
72 changes: 37 additions & 35 deletions components/Collections/samples/AdvancedCollectionViewSample.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,73 @@
// See the LICENSE file in the project root for more information.

using CommunityToolkit.WinUI.Collections;
using System.Diagnostics.CodeAnalysis;

namespace CollectionsExperiment.Samples;

[ToolkitSample(id: nameof(AdvancedCollectionViewSample), "AdvancedCollectionView", description: $"A sample for showing how to create and use a {nameof(AdvancedCollectionView)}.")]
[ToolkitSample(id: nameof(AdvancedCollectionViewSample), "AdvancedCollectionView", description: $"A sample for showing how to create and use a {nameof(AdvancedCollectionView)} for sorting and filtering.")]
public sealed partial class AdvancedCollectionViewSample : Page
{
public ObservableCollection<Person>? oc;
public ObservableCollection<Employee> EmployeeCollection { get; private set; }

public AdvancedCollectionView CollectionView { get; private set; }

public AdvancedCollectionViewSample()
{
this.InitializeComponent();
Setup();
}

[MemberNotNull(nameof(EmployeeCollection))]
[MemberNotNull(nameof(CollectionView))]
private void Setup()
{
// left list
oc = new ObservableCollection<Person>
EmployeeCollection = new()
{
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" },
new() { Name = "Staff" },
new() { Name = "42" },
new() { Name = "Swan" },
new() { Name = "Orchid" },
new() { Name = "15" },
new() { Name = "Flame" },
new() { Name = "16" },
new() { Name = "Arrow" },
new() { Name = "Tempest" },
new() { Name = "23" },
new() { Name = "Pearl" },
new() { Name = "Hydra" },
new() { Name = "Lamp Post" },
new() { Name = "4" },
new() { Name = "Looking Glass" },
new() { Name = "8" },
};

LeftList.ItemsSource = oc;

// right list
var acv = new AdvancedCollectionView(oc);
int nul;
acv.Filter = x => !int.TryParse(((Person)x).Name, out nul);
acv.SortDescriptions.Add(new SortDescription("Name", SortDirection.Ascending));
AdvancedCollectionView acv = new(EmployeeCollection);
acv.Filter = x => !int.TryParse(((Employee)x).Name, out _);
acv.SortDescriptions.Add(new(nameof(Employee.Name), SortDirection.Ascending));

RightList.ItemsSource = acv;
CollectionView = acv;
}

private void Add_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(NewItemBox.Text))
{
oc!.Insert(0, new Person { Name = NewItemBox.Text });
EmployeeCollection.Insert(0, new Employee { Name = NewItemBox.Text });
NewItemBox.Text = "";
}
}
}

/// <summary>
/// A sample class used to show how to use the <see cref="AdvancedCollectionView"/> class.
/// </summary>
public partial class Employee
{
/// <summary>
/// A sample class used to show how to use the <see cref="IIncrementalSource{TSource}"/> interface.
/// Gets or sets the name of the person.
/// </summary>
public class Person
{
/// <summary>
/// Gets or sets the name of the person.
/// </summary>
public string? Name { get; set; }
}
public string? Name { get; set; }
}
6 changes: 6 additions & 0 deletions components/Collections/samples/Collections.Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- 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. -->
<!-- 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="CollectionsExperiment.Samples.IncrementalLoadingCollectionSample"
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:local="using:IncrementalLoadingCollectionExperiment.Samples"
xmlns:local="using:CollectionsExperiment.Samples"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

Expand All @@ -19,18 +19,18 @@
<TextBlock Text="Items are loaded incrementally when the view needs to show them (i.e., when the user scrolls the ListView)"
TextWrapping="Wrap" />
<Button Margin="0,12,0,12"
Click="RefreshCollection"
Click="{x:Bind PeopleSource.RefreshAsync}"
Content="Refresh collection"
Style="{StaticResource AccentButtonStyle}" />
<TextBlock>
<Run Text="Is loading:" />
<Run FontWeight="SemiBold"
Text="{Binding IsLoading, Mode=OneWay}" />
Text="{x:Bind PeopleSource.IsLoading, Mode=OneWay}" />
</TextBlock>
<TextBlock>
<Run Text="Has more items:" />
<Run FontWeight="SemiBold"
Text="{Binding HasMoreItems, Mode=OneWay}" />
Text="{x:Bind PeopleSource.HasMoreItems, Mode=OneWay}" />
</TextBlock>

</StackPanel>
Expand All @@ -43,9 +43,10 @@
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="4">
<ListView x:Name="PeopleListView">
<ListView x:Name="PeopleListView"
ItemsSource="{x:Bind PeopleSource, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate>
<DataTemplate x:DataType="local:Person">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
Expand All @@ -58,7 +59,7 @@
<TextBlock Grid.Column="1"
Margin="12"
VerticalAlignment="Center"
Text="{Binding Name}" />
Text="{x:Bind Name}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,20 @@ namespace CollectionsExperiment.Samples;
[ToolkitSample(id: nameof(IncrementalLoadingCollectionSample), "Incremental Loading Collection", description: $"A sample for showing how to create and use a IncrementalLoadingCollection.")]
public sealed partial class IncrementalLoadingCollectionSample : Page
{
// IncrementalLoadingCollection can be bound to a GridView or a ListView. In this case it is a ListView called PeopleListView.
public IncrementalLoadingCollection<PeopleSource, Person> PeopleSource { get; set; } = new(new PeopleSource());

public IncrementalLoadingCollectionSample()
{
this.InitializeComponent();
Load();
}
private void Load()
{
// IncrementalLoadingCollection can be bound to a GridView or a ListView. In this case it is a ListView called PeopleListView.
var collection = new IncrementalLoadingCollection<PeopleSource, Person>(new PeopleSource());
PeopleListView.ItemsSource = collection;

// Binds the collection to the page DataContext in order to use its IsLoading and HasMoreItems properties.
DataContext = collection;
}

private async void RefreshCollection(object sender, RoutedEventArgs e)
{
var collection = (IncrementalLoadingCollection<PeopleSource, Person>)PeopleListView.ItemsSource;
await collection.RefreshAsync();
}
}

/// <summary>
/// A sample implementation of the <see cref="IIncrementalSource{TSource}"/> interface.
/// </summary>
/// <seealso cref="IIncrementalSource{TSource}"/>
public class PeopleSource : IIncrementalSource<Person>
public partial class PeopleSource : IIncrementalSource<Person>
{
private readonly List<Person> _people;

Expand Down Expand Up @@ -94,7 +81,7 @@ public PeopleSource()
/// <summary>
/// A sample class used to show how to use the <see cref="IIncrementalSource{TSource}"/> interface.
/// </summary>
public class Person
public partial class Person
{
/// <summary>
/// Gets or sets the name of the person.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
<RootNamespace>CommunityToolkit.WinUI.CollectionsRns</RootNamespace>
<PackageReadmeFile>ReadMe.md</PackageReadmeFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
<RootNamespace>CommunityToolkit.WinUI.Controls.ColorPickerRns</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
<RootNamespace>CommunityToolkit.WinUI.HelpersRns</RootNamespace>
<PackageReadmeFile>ReadMe.md</PackageReadmeFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 2120f62

Please sign in to comment.