Skip to content

Commit 1b4cdc8

Browse files
committed
Merge branch 'Color-Helper' of https://github.com/Avid29/CommunityToolkit-Windows into Color-Helper
2 parents 6409b10 + 27694dc commit 1b4cdc8

20 files changed

+806
-259
lines changed

components/Collections/samples/AdvancedCollectionViewSample.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ private void Setup()
4848
// right list
4949
AdvancedCollectionView acv = new(EmployeeCollection);
5050
acv.Filter = x => !int.TryParse(((Employee)x).Name, out _);
51-
acv.SortDescriptions.Add(new(nameof(Employee.Name), SortDirection.Ascending));
51+
acv.SortDescriptions.Add(new SortDescription<Employee>(nameof(Employee.Name), SortDirection.Ascending));
5252

5353
CollectionView = acv;
5454
}

components/Collections/src/AdvancedCollectionView/AdvancedCollectionView.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ namespace CommunityToolkit.WinUI.Collections;
1313
/// <summary>
1414
/// A collection view implementation that supports filtering, sorting and incremental loading
1515
/// </summary>
16-
#if NET8_0_OR_GREATER
17-
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Item sorting uses reflection to get property types and may not be AOT compatible.")]
18-
#endif
1916
public partial class AdvancedCollectionView : IAdvancedCollectionView, INotifyPropertyChanged, ISupportIncrementalLoading, IComparer<object>
2017
{
2118
private readonly List<object> _view;
@@ -383,7 +380,7 @@ public Predicate<object> Filter
383380
int IComparer<object>.Compare(object x, object y)
384381
#pragma warning restore CA1033 // Interface methods should be callable by child types
385382
{
386-
if (!_sortProperties.Any())
383+
if (_sortProperties.Count == 0)
387384
{
388385
var listType = _source?.GetType();
389386
Type type;
@@ -401,7 +398,7 @@ int IComparer<object>.Compare(object x, object y)
401398
{
402399
if (!string.IsNullOrEmpty(sd.PropertyName))
403400
{
404-
_sortProperties[sd.PropertyName] = type.GetProperty(sd.PropertyName);
401+
_sortProperties[sd.PropertyName] = sd.GetProperty(type);
405402
}
406403
}
407404
}
@@ -419,8 +416,8 @@ int IComparer<object>.Compare(object x, object y)
419416
{
420417
var pi = _sortProperties[sd.PropertyName];
421418

422-
cx = pi.GetValue(x!);
423-
cy = pi.GetValue(y!);
419+
cx = pi.GetValue(x);
420+
cy = pi.GetValue(y);
424421
}
425422

426423
var cmp = sd.Comparer.Compare(cx, cy);

components/Collections/src/AdvancedCollectionView/SortDescription.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Collections;
6+
using System.Diagnostics.CodeAnalysis;
67

78
namespace CommunityToolkit.WinUI.Collections;
89

@@ -14,7 +15,7 @@ public class SortDescription
1415
/// <summary>
1516
/// Gets the name of property to sort on
1617
/// </summary>
17-
public string PropertyName { get; }
18+
public string? PropertyName { get; }
1819

1920
/// <summary>
2021
/// Gets the direction of sort
@@ -33,8 +34,10 @@ public class SortDescription
3334
/// <param name="direction">Direction of sort</param>
3435
/// <param name="comparer">Comparer to use. If null, will use default comparer</param>
3536
public SortDescription(SortDirection direction, IComparer? comparer = null)
36-
: this(null!, direction, comparer!)
3737
{
38+
PropertyName = null;
39+
Direction = direction;
40+
Comparer = comparer ?? ObjectComparer.Instance;
3841
}
3942

4043
/// <summary>
@@ -43,13 +46,23 @@ public SortDescription(SortDirection direction, IComparer? comparer = null)
4346
/// <param name="propertyName">Name of property to sort on</param>
4447
/// <param name="direction">Direction of sort</param>
4548
/// <param name="comparer">Comparer to use. If null, will use default comparer</param>
49+
#if NET8_0_OR_GREATER
50+
[RequiresUnreferencedCode("Item sorting with the property name uses reflection to get the property and is not trim-safe. Either use SortDescription<T> to preserve the required metadata, or use the other constructor without a property name.")]
51+
#endif
4652
public SortDescription(string propertyName, SortDirection direction, IComparer? comparer = null)
4753
{
4854
PropertyName = propertyName;
4955
Direction = direction;
5056
Comparer = comparer ?? ObjectComparer.Instance;
5157
}
5258

59+
#if NET8_0_OR_GREATER
60+
[UnconditionalSuppressMessage("Trimming", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.",
61+
Justification = "The path which does reflection is only triggered if the user uses the constructor with RequiresUnreferencedCode, which will inform them of the risk.")]
62+
#endif
63+
internal virtual PropertyInfo? GetProperty(Type type)
64+
=> PropertyName != null ? type.GetProperty(PropertyName) : null;
65+
5366
private class ObjectComparer : IComparer
5467
{
5568
public static readonly IComparer Instance = new ObjectComparer();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections;
6+
using System.Diagnostics.CodeAnalysis;
7+
8+
namespace CommunityToolkit.WinUI.Collections;
9+
10+
/// <summary>
11+
/// A generic version of <see cref="SortDescription"/> which preserves the required metadata for reflection-based sorting.
12+
/// </summary>
13+
/// <typeparam name="T">The type to sort</typeparam>
14+
public sealed class SortDescription<
15+
#if NET8_0_OR_GREATER
16+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
17+
#endif
18+
T> : SortDescription
19+
{
20+
private readonly PropertyInfo _prop;
21+
22+
/// <summary>
23+
/// Initializes a new instance of the <see cref="SortDescription{T}"/> class.
24+
/// </summary>
25+
/// <param name="propertyName">Name of property to sort on</param>
26+
/// <param name="direction">Direction of sort</param>
27+
/// <param name="comparer">Comparer to use. If null, will use default comparer</param>
28+
#if NET8_0_OR_GREATER
29+
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
30+
Justification = "This class preserves metadata and ensures at runtime that the received type is compatible.")]
31+
#endif
32+
public SortDescription(string propertyName, SortDirection direction, IComparer? comparer = null) : base(propertyName, direction, comparer)
33+
{
34+
_prop = typeof(T).GetProperty(propertyName) ?? throw new ArgumentException($"Could not find property {propertyName}");
35+
}
36+
37+
internal override PropertyInfo? GetProperty(Type type) =>
38+
(_prop.DeclaringType is not null && _prop.DeclaringType.IsAssignableFrom(type)) ? _prop : throw new ArgumentException("This instance of SortDescription is not compatible with the desired type");
39+
}

components/Converters/samples/DoubleToObjectConverterSample.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<Page.Resources>
1212
<converters:DoubleToObjectConverter x:Key="DoubleToObjectConverter"
1313
FalseValue="{ThemeResource SystemFillColorSuccessBrush}"
14-
GreaterThan="7"
15-
LessThan="3"
14+
GreaterThan="3"
15+
LessThan="7"
1616
TrueValue="{ThemeResource SystemFillColorCriticalBrush}" />
1717
</Page.Resources>
1818

0 commit comments

Comments
 (0)