Skip to content

Commit 862b43a

Browse files
committed
Merge branch 'main' into winui
# Conflicts: # CommunityToolkit.WinUI.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml.cs # version.json
2 parents be7f299 + 84adf91 commit 862b43a

File tree

16 files changed

+253
-54
lines changed

16 files changed

+253
-54
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ public void Execute(GeneratorExecutionContext context)
4242
return;
4343
}
4444

45-
// Validate the language version
46-
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
45+
// Validate the language version (this needs at least C# 8.0 due to static local functions being used).
46+
// If a lower C# version is set, just skip the execution silently. The fallback path will be used just fine.
47+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp8 })
4748
{
48-
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
49+
return;
4950
}
5051

5152
// Get the symbol for the required attributes

CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ public void Execute(GeneratorExecutionContext context)
3939
return;
4040
}
4141

42-
// Validate the language version
43-
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
42+
// Like in the ObservableValidator.ValidateALlProperties generator, execution is skipped if C# >= 8.0 isn't available
43+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp8 })
4444
{
45-
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
45+
return;
4646
}
4747

4848
// Get the symbol for the IRecipient<T> interface type

CommunityToolkit.Mvvm/ComponentModel/ObservableValidator.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,21 @@ static Action<object> GetValidationAction(Type type)
488488
// Fallback method to create the delegate with a compiled LINQ expression
489489
static Action<object> GetValidationActionFallback(Type type)
490490
{
491+
// Get the collection of all properties to validate
492+
(string Name, MethodInfo GetMethod)[] validatableProperties = (
493+
from property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
494+
where property.GetIndexParameters().Length == 0 &&
495+
property.GetCustomAttributes<ValidationAttribute>(true).Any()
496+
let getMethod = property.GetMethod
497+
where getMethod is not null
498+
select (property.Name, getMethod)).ToArray();
499+
500+
// Short path if there are no properties to validate
501+
if (validatableProperties.Length == 0)
502+
{
503+
return static _ => { };
504+
}
505+
491506
// MyViewModel inst0 = (MyViewModel)arg0;
492507
ParameterExpression arg0 = Expression.Parameter(typeof(object));
493508
UnaryExpression inst0 = Expression.Convert(arg0, type);
@@ -513,14 +528,10 @@ static Action<object> GetValidationActionFallback(Type type)
513528
// ObservableValidator externally, but that is fine because IL doesn't really have
514529
// a concept of member visibility, that's purely a C# build-time feature.
515530
BlockExpression body = Expression.Block(
516-
from property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
517-
where property.GetIndexParameters().Length == 0 &&
518-
property.GetCustomAttributes<ValidationAttribute>(true).Any()
519-
let getter = property.GetMethod
520-
where getter is not null
531+
from property in validatableProperties
521532
select Expression.Call(inst0, validateMethod, new Expression[]
522533
{
523-
Expression.Convert(Expression.Call(inst0, getter), typeof(object)),
534+
Expression.Convert(Expression.Call(inst0, property.GetMethod), typeof(object)),
524535
Expression.Constant(property.Name)
525536
}));
526537

CommunityToolkit.Mvvm/Messaging/IMessengerExtensions.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,20 @@ static Action<IMessenger, object, TToken> LoadRegistrationMethodsForType(Type re
153153
// The LINQ codegen bloat is not really important for the same reason.
154154
static Action<IMessenger, object, TToken> LoadRegistrationMethodsForTypeFallback(Type recipientType)
155155
{
156+
// Get the collection of validation methods
157+
MethodInfo[] registrationMethods = (
158+
from interfaceType in recipientType.GetInterfaces()
159+
where interfaceType.IsGenericType &&
160+
interfaceType.GetGenericTypeDefinition() == typeof(IRecipient<>)
161+
let messageType = interfaceType.GenericTypeArguments[0]
162+
select MethodInfos.RegisterIRecipient.MakeGenericMethod(messageType, typeof(TToken))).ToArray();
163+
164+
// Short path if there are no message handlers to register
165+
if (registrationMethods.Length == 0)
166+
{
167+
return static (_, _, _) => { };
168+
}
169+
156170
// Input parameters (IMessenger instance, non-generic recipient, token)
157171
ParameterExpression
158172
arg0 = Expression.Parameter(typeof(IMessenger)),
@@ -178,11 +192,7 @@ static Action<IMessenger, object, TToken> LoadRegistrationMethodsForTypeFallback
178192
// We also add an explicit object conversion to cast the input recipient type to
179193
// the actual specific type, so that the exposed message handlers are accessible.
180194
BlockExpression body = Expression.Block(
181-
from interfaceType in recipientType.GetInterfaces()
182-
where interfaceType.IsGenericType &&
183-
interfaceType.GetGenericTypeDefinition() == typeof(IRecipient<>)
184-
let messageType = interfaceType.GenericTypeArguments[0]
185-
let registrationMethod = MethodInfos.RegisterIRecipient.MakeGenericMethod(messageType, typeof(TToken))
195+
from registrationMethod in registrationMethods
186196
select Expression.Call(registrationMethod, new Expression[]
187197
{
188198
arg0,

CommunityToolkit.WinUI.SampleApp/SamplePages/ImageBlendBrush/ImageBlendBrushXaml.bind

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<Border Grid.Column="0">
1919
<Border.Background>
2020
<media:ImageBlendBrush
21-
Source="/SamplePages/DropShadowPanel/Unicorn.png"
21+
Source="/SamplePages/Shadows/Unicorn.png"
2222
Stretch="@[Unicorn Stretch:Enum:Stretch.None]"
2323
Mode="@[Unicorn Blend Mode:Enum:ImageBlendMode.ColorBurn]"
2424
/>
@@ -27,7 +27,7 @@
2727
<Border Grid.Column="1">
2828
<Border.Background>
2929
<media:ImageBlendBrush
30-
Source="/SamplePages/DropShadowPanel/Trex.png"
30+
Source="/SamplePages/Shadows/Trex.png"
3131
Stretch="@[Trex Stretch:Enum:Stretch.None]"
3232
Mode="@[Trex Blend Mode:Enum:ImageBlendMode.Subtract]"
3333
/>

CommunityToolkit.WinUI.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Numerics;
77
using CommunityToolkit.WinUI.UI;
8+
using CommunityToolkit.WinUI.UI.Animations;
89
using Microsoft.UI.Xaml;
910
using Microsoft.UI.Xaml.Controls;
1011
using Microsoft.UI.Xaml.Hosting;
@@ -18,6 +19,8 @@ public sealed partial class ImplicitAnimationsPage : IXamlRenderListener
1819
{
1920
private Random _random = new Random();
2021
private UIElement _element;
22+
private ImplicitAnimationSet _animationSet;
23+
private bool _areAnimationsToggled;
2124

2225
public ImplicitAnimationsPage()
2326
{
@@ -28,6 +31,8 @@ public ImplicitAnimationsPage()
2831
public void OnXamlRendered(FrameworkElement control)
2932
{
3033
_element = control.FindChild("Element");
34+
_animationSet = Implicit.GetAnimations(_element);
35+
_areAnimationsToggled = true;
3136
}
3237

3338
private void Load()
@@ -60,6 +65,16 @@ private void Load()
6065
1);
6166
}
6267
});
68+
69+
SampleController.Current.RegisterNewCommand("Toggle animations", (sender, args) =>
70+
{
71+
if (_element != null)
72+
{
73+
Implicit.SetAnimations(_element, _areAnimationsToggled ? null : _animationSet);
74+
75+
_areAnimationsToggled = !_areAnimationsToggled;
76+
}
77+
});
6378
}
6479
}
6580
}

CommunityToolkit.WinUI.SampleApp/SamplePages/PipelineBrush/PipelineBrushXaml.bind

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<media:BlurEffect Amount="16"/>
2727
<media:ShadeEffect Color="#FF222222" Intensity="0.2"/>
2828
<media:BlendEffect Mode="Overlay" Source="{media:TileSource Uri=ms-appx:///Assets/BrushAssets/NoiseTexture.png}"/>
29-
<media:BlendEffect Mode="Overlay" Source="{media:ImageSource Uri=ms-appx:///SamplePages/DropShadowPanel/Unicorn.png}"/>
29+
<media:BlendEffect Mode="Overlay" Source="{media:ImageSource Uri=ms-appx:///SamplePages/Shadows/Unicorn.png}"/>
3030
</media:PipelineBrush>
3131
</Border.Background>
3232
</Border>

CommunityToolkit.WinUI.SampleApp/SamplePages/VisualEffectFactory/VisualEffectFactory.bind

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<media:BlurEffect Amount="16"/>
2626
<media:ShadeEffect Color="#FF222222" Intensity="0.2"/>
2727
<media:BlendEffect Mode="Overlay" Source="{media:TileSource Uri=ms-appx:///Assets/BrushAssets/NoiseTexture.png}"/>
28-
<media:BlendEffect Mode="Overlay" Source="{media:ImageSource Uri=ms-appx:///SamplePages/DropShadowPanel/Unicorn.png}"/>
28+
<media:BlendEffect Mode="Overlay" Source="{media:ImageSource Uri=ms-appx:///SamplePages/Shadows/Unicorn.png}"/>
2929
</media:PipelineVisualFactory>
3030
</media:UIElementExtensions.VisualFactory>
3131
</Border>

CommunityToolkit.WinUI.UI.Animations/Implicit.cs

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static ImplicitAnimationSet GetShowAnimations(UIElement element)
5353

5454
if (collection is null)
5555
{
56-
element.SetValue(ShowAnimationsProperty, collection = new());
56+
element.SetValue(ShowAnimationsProperty, collection = new ImplicitAnimationSet());
5757
}
5858

5959
return collection;
@@ -80,7 +80,7 @@ public static ImplicitAnimationSet GetHideAnimations(UIElement element)
8080

8181
if (collection is null)
8282
{
83-
element.SetValue(HideAnimationsProperty, collection = new());
83+
element.SetValue(HideAnimationsProperty, collection = new ImplicitAnimationSet());
8484
}
8585

8686
return collection;
@@ -107,7 +107,7 @@ public static ImplicitAnimationSet GetAnimations(UIElement element)
107107

108108
if (collection is null)
109109
{
110-
element.SetValue(AnimationsProperty, collection = new());
110+
element.SetValue(AnimationsProperty, collection = new ImplicitAnimationSet());
111111
}
112112

113113
return collection;
@@ -145,15 +145,21 @@ static void OnAnimationsChanged(object? sender, EventArgs e)
145145
oldCollection.AnimationsChanged -= OnAnimationsChanged;
146146
}
147147

148-
if (d is UIElement element &&
149-
e.NewValue is ImplicitAnimationSet collection)
148+
if (d is UIElement element)
150149
{
151-
collection.ParentReference = new(element);
152-
collection.AnimationsChanged -= OnAnimationsChanged;
153-
collection.AnimationsChanged += OnAnimationsChanged;
150+
if (e.NewValue is ImplicitAnimationSet collection)
151+
{
152+
collection.ParentReference = new(element);
153+
collection.AnimationsChanged -= OnAnimationsChanged;
154+
collection.AnimationsChanged += OnAnimationsChanged;
154155

155-
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
156-
ElementCompositionPreview.SetImplicitShowAnimation(element, collection.GetCompositionAnimationGroup(element));
156+
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
157+
ElementCompositionPreview.SetImplicitShowAnimation(element, collection.GetCompositionAnimationGroup(element));
158+
}
159+
else
160+
{
161+
ElementCompositionPreview.SetImplicitShowAnimation(element, null);
162+
}
157163
}
158164
}
159165

@@ -179,15 +185,21 @@ static void OnAnimationsChanged(object? sender, EventArgs e)
179185
oldCollection.AnimationsChanged -= OnAnimationsChanged;
180186
}
181187

182-
if (d is UIElement element &&
183-
e.NewValue is ImplicitAnimationSet collection)
188+
if (d is UIElement element)
184189
{
185-
collection.ParentReference = new(element);
186-
collection.AnimationsChanged -= OnAnimationsChanged;
187-
collection.AnimationsChanged += OnAnimationsChanged;
190+
if (e.NewValue is ImplicitAnimationSet collection)
191+
{
192+
collection.ParentReference = new(element);
193+
collection.AnimationsChanged -= OnAnimationsChanged;
194+
collection.AnimationsChanged += OnAnimationsChanged;
188195

189-
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
190-
ElementCompositionPreview.SetImplicitHideAnimation(element, collection.GetCompositionAnimationGroup(element));
196+
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
197+
ElementCompositionPreview.SetImplicitHideAnimation(element, collection.GetCompositionAnimationGroup(element));
198+
}
199+
else
200+
{
201+
ElementCompositionPreview.SetImplicitHideAnimation(element, null);
202+
}
191203
}
192204
}
193205

@@ -213,15 +225,21 @@ static void OnAnimationsChanged(object? sender, EventArgs e)
213225
oldCollection.AnimationsChanged -= OnAnimationsChanged;
214226
}
215227

216-
if (d is UIElement element &&
217-
e.NewValue is ImplicitAnimationSet collection)
228+
if (d is UIElement element)
218229
{
219-
collection.ParentReference = new(element);
220-
collection.AnimationsChanged -= OnAnimationsChanged;
221-
collection.AnimationsChanged += OnAnimationsChanged;
230+
if (e.NewValue is ImplicitAnimationSet collection)
231+
{
232+
collection.ParentReference = new(element);
233+
collection.AnimationsChanged -= OnAnimationsChanged;
234+
collection.AnimationsChanged += OnAnimationsChanged;
222235

223-
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
224-
ElementCompositionPreview.GetElementVisual(element).ImplicitAnimations = collection.GetImplicitAnimationCollection(element);
236+
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
237+
ElementCompositionPreview.GetElementVisual(element).ImplicitAnimations = collection.GetImplicitAnimationCollection(element);
238+
}
239+
else
240+
{
241+
ElementCompositionPreview.GetElementVisual(element).ImplicitAnimations = null;
242+
}
225243
}
226244
}
227245
}

CommunityToolkit.WinUI/Extensions/DispatcherQueueTimerExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static void Debounce(this DispatcherQueueTimer timer, Action action, Time
6262
timer.Tick += Timer_Tick;
6363

6464
// Store/Update function
65-
_debounceInstances.AddOrUpdate(timer, action, (k, v) => v);
65+
_debounceInstances.AddOrUpdate(timer, action, (k, v) => action);
6666
}
6767

6868
// Start the timer to keep track of the last call here.

0 commit comments

Comments
 (0)