diff --git a/.editorconfig b/.editorconfig
index 50eeccedc3f..36629f6b744 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -324,4 +324,7 @@ dotnet_diagnostic.SA1652.severity = none
dotnet_diagnostic.SA1629.severity = none # DocumentationTextMustEndWithAPeriod: Let's enable this rule back when we shift to WinUI3 (v8.x). If we do it now, it would mean more than 400 file changes.
dotnet_diagnostic.SA1413.severity = none # UseTrailingCommasInMultiLineInitializers: This would also mean a lot of changes at the end of all multiline initializers. It's also debatable if we want this or not.
-dotnet_diagnostic.SA1314.severity = none # TypeParameterNamesMustBeginWithT: We do have a few templates that don't start with T. We need to double check that changing this is not a breaking change. If not, we can re-enable this.
\ No newline at end of file
+dotnet_diagnostic.SA1314.severity = none # TypeParameterNamesMustBeginWithT: We do have a few templates that don't start with T. We need to double check that changing this is not a breaking change. If not, we can re-enable this.
+dotnet_diagnostic.SA1000.severity = none # Hide warnings when using the new() expression from C# 9.
+dotnet_diagnostic.SA1313.severity = none # Hide warnings for record parameters.
+dotnet_diagnostic.SA1101.severity = none # Hide warnings when accessing properties without "this".
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Assets/Llama.mp3 b/Microsoft.Toolkit.Uwp.SampleApp/Assets/Llama.mp3
new file mode 100644
index 00000000000..20fa5514349
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/Assets/Llama.mp3 differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
index d89fc02aa6b..b0e9f84eb42 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
@@ -112,9 +112,6 @@
10.1901.28001
-
- 6.1.0-build.6
- 2.4.2
@@ -135,6 +132,7 @@
+
@@ -269,6 +267,7 @@
+
@@ -291,7 +290,6 @@
-
@@ -300,7 +298,6 @@
-
@@ -322,7 +319,6 @@
-
@@ -333,18 +329,14 @@
-
-
-
-
+
-
@@ -377,11 +369,7 @@
-
-
-
-
@@ -393,13 +381,7 @@
-
-
-
-
-
-
@@ -418,9 +400,7 @@
-
-
-
+ Designer
@@ -437,8 +417,6 @@
-
- Designer
@@ -608,6 +586,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -811,9 +810,6 @@
BladePage.xaml
-
- BlurBehaviorPage.xaml
- AlignmentGridPage.xaml
@@ -823,9 +819,6 @@
MicrosoftTranslatorPage.xaml
-
- SaturationBehaviorPage.xaml
- TileControlPage.xaml
@@ -846,9 +839,6 @@
-
- LightBehaviorPage.xaml
- LinkedInPage.xaml
@@ -864,8 +854,8 @@
PrintHelperPage.xaml
-
- ReorderGridPage.xaml
+
+ ItemsReorderAnimationPage.xamlRotatorTilePage.xaml
@@ -894,12 +884,6 @@
TwitterPage.xaml
-
- OffsetBehaviorPage.xaml
-
-
- FadeBehaviorPage.xaml
- ImageExPage.xaml
@@ -913,12 +897,6 @@
WeatherLiveTileAndToastPage.xaml
-
- RotateBehaviorPage.xaml
-
-
- ScaleBehaviorPage.xaml
- RadialGaugePage.xaml
@@ -1256,10 +1234,6 @@
DesignerMSBuild:Compile
-
- MSBuild:Compile
- Designer
- MSBuild:CompileDesigner
@@ -1276,10 +1250,6 @@
MSBuild:CompileDesigner
-
- Designer
- MSBuild:Compile
- MSBuild:CompileDesigner
@@ -1308,10 +1278,6 @@
MSBuild:CompileDesigner
-
- Designer
- MSBuild:Compile
- DesignerMSBuild:Compile
@@ -1332,7 +1298,7 @@
MSBuild:CompileDesigner
-
+ DesignerMSBuild:Compile
@@ -1344,14 +1310,6 @@
MSBuild:CompileDesigner
-
- Designer
- MSBuild:Compile
-
-
- Designer
- MSBuild:Compile
- DesignerMSBuild:Compile
@@ -1404,14 +1362,6 @@
MSBuild:CompileDesigner
-
- Designer
- MSBuild:Compile
-
-
- Designer
- MSBuild:Compile
- DesignerMSBuild:Compile
@@ -1486,6 +1436,10 @@
{1ae2cb5c-58a0-4f12-8e6f-2cd4aaadb34c}Microsoft.Toolkit.Uwp.Samples.BackgroundTasks
+
+ {d4ff799d-0df2-495a-adc9-3bbc4aef8971}
+ Microsoft.Toolkit.Uwp.UI.Behaviors
+ {daeb9cec-c817-33b2-74b2-bc379380db72}Microsoft.Toolkit.Uwp.UI.Controls.DataGrid
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
index 0707df494f7..1db3fbd9e7e 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Models/Sample.cs
@@ -16,8 +16,6 @@
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using Microsoft.Toolkit.Graph.Converters;
-using Microsoft.Toolkit.Graph.Providers;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.Input.GazeInteraction;
using Microsoft.Toolkit.Uwp.SampleApp.Models;
@@ -660,16 +658,16 @@ private static Type LookForTypeByName(string typeName)
}
// Search in Microsoft.Toolkit.Graph.Controls
- var graphControlsProxyType = typeof(UserToPersonConverter);
- assembly = graphControlsProxyType.GetTypeInfo().Assembly;
-
- foreach (var typeInfo in assembly.ExportedTypes)
- {
- if (typeInfo.Name == typeName)
- {
- return typeInfo;
- }
- }
+ //var graphControlsProxyType = typeof(UserToPersonConverter);
+ //assembly = graphControlsProxyType.GetTypeInfo().Assembly;
+
+ //foreach (var typeInfo in assembly.ExportedTypes)
+ //{
+ // if (typeInfo.Name == typeName)
+ // {
+ // return typeInfo;
+ // }
+ //}
// Search in Microsoft.Toolkit.Uwp.UI.Animations
var animationsProxyType = EasingType.Default;
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml
index 0607623cd30..bda1ccfa186 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml
@@ -1,158 +1,176 @@

-
-
-
+
+
+
-
-
+
-
+ Click="RecentSample_Click"
+ Style="{StaticResource AboutHyperlinkButtonStyle}">
+
-
-
-
+
+
+
-
-
+
-
+
+ Text="{x:Bind Published.ToString('MMM d', {x:Null})}" />
-
-
+
-
+ Style="{StaticResource AboutHyperlinkButtonStyle}">
+
-
+
-
+
+ ShadowOpacity="0"
+ Color="Black">
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+ Recent Activity
-
+
-
+ ItemsPanel="{StaticResource ItemsWrapGridHorizontalTemplate}"
+ ItemsSource="{x:Bind RecentSamples, Mode=OneWay}" />
@@ -161,36 +179,49 @@
Grid.Row="3"
Grid.RowSpan="3"
Grid.Column="4"
- ItemsPanel="{StaticResource ItemsWrapGridHorizontalTemplate}"
- animations:Implicit.Animations="{StaticResource ImplicitOffset}">
-
-
-
-
+ animations:Implicit.Animations="{StaticResource ImplicitOffset}"
+ ItemsPanel="{StaticResource ItemsWrapGridHorizontalTemplate}">
+
+
+
+
-
+ Release Notes
-
+
+ ItemsSource="{x:Bind LandingPageLinks.Resources, Mode=OneWay}">
-
-
-
+
+
+
-
+
@@ -204,18 +235,25 @@
+ animations:Implicit.Animations="{StaticResource ImplicitOffset}"
+ BorderBrush="{ThemeResource Border-AboutPage-Horizontal}"
+ BorderThickness="0,1,0,0" />
-
-
+ animations:Implicit.Animations="{StaticResource ImplicitOffset}"
+ BorderBrush="{ThemeResource Border-AboutPage-Horizontal}"
+ BorderThickness="0,1,0,0" />
+
+ Privacy statement
@@ -224,12 +262,20 @@
-
-
+
+
-
-
+
+
@@ -267,7 +313,7 @@
-
+
@@ -303,7 +349,7 @@
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs
index 2040485db8b..6546c73a9a0 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Pages/About.xaml.cs
@@ -151,8 +151,7 @@ private async Task Init()
From = 0,
To = 1,
Duration = TimeSpan.FromMilliseconds(300),
- Delay = TimeSpan.FromMilliseconds(counter++ * delay),
- SetInitialValueBeforeDelay = true
+ Delay = TimeSpan.FromMilliseconds(counter++ * delay)
});
}
}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/InvokeActionsActivity.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/InvokeActionsActivity.bind
new file mode 100644
index 00000000000..94b95d6851e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/InvokeActionsActivity.bind
@@ -0,0 +1,54 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/StartAnimationActivity.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/StartAnimationActivity.bind
new file mode 100644
index 00000000000..29a56db3b85
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Activities/StartAnimationActivity.bind
@@ -0,0 +1,50 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorCode.bind
new file mode 100644
index 00000000000..8e2c5c48386
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorCode.bind
@@ -0,0 +1,14 @@
+// XAML UIElement
+
+
+// C# - Blur can be applied to any UIElement. In this case it is an image called ToolkitLogo.
+using Microsoft.Toolkit.Uwp.UI.Animations;
+
+// Create and attacha a sprite visual with an animatable blur effect
+var sprite = await PipelineBuilder
+ .FromBackdrop()
+ .Blur(0, out EffectAnimation blurAnimation)
+ .AttachAsync(ToolkitLogo, ToolkitLogo);
+
+// Start the animation on the applied brush
+blurAnimation(sprite.Brush, 32, TimeSpan.FromSeconds(3));
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorXaml.bind
new file mode 100644
index 00000000000..3425f482504
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/BlurBehaviorXaml.bind
@@ -0,0 +1,42 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorCode.bind
new file mode 100644
index 00000000000..6a20d6a0e78
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorCode.bind
@@ -0,0 +1,12 @@
+// XAML UIElement
+
+
+// C# - Offset can be applied to any UIElement. In this case it is an image called ToolkitLogo.
+using Microsoft.Toolkit.Uwp.UI.Animations;
+
+// Create and start the animation. Note that animating the offset will
+// change how the item is also positioned within its parent item. If you
+// want to animate the position of an element with respect to its original
+// relative position to its parent, use a translation animation instead.
+await AnimationBuilder.Create().Offset(to: new Vector2(20, 30), duration: TimeSpan.FromSeconds(3)).StartAsync(ToolkitLogo);
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorXaml.bind
new file mode 100644
index 00000000000..3e46cc4021d
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/OffsetBehaviorXaml.bind
@@ -0,0 +1,35 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorCode.bind
similarity index 67%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorCode.bind
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorCode.bind
index a7f9916c585..d19ef0f5e87 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorCode.bind
@@ -4,7 +4,4 @@
// C# - Rotate can be applied to any UIElement. In this case it is an image called ToolkitLogo.
using Microsoft.Toolkit.Uwp.UI.Animations;
-await ToolkitLogo.Rotate(value: 90.0f,
- centerX: 0.5f,
- centerY: 0.0f,
- duration: 10, delay: 0).StartAsync();
+await AnimationBuilder.Create().RotationInDegrees(to: 90, duration: TimeSpan.FromSeconds(3)).StartAsync(ToolkitLogo);
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorXaml.bind
new file mode 100644
index 00000000000..0e7450e72d9
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/RotateBehaviorXaml.bind
@@ -0,0 +1,41 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorCode.bind
new file mode 100644
index 00000000000..5d89f4bb8a3
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorCode.bind
@@ -0,0 +1,14 @@
+// XAML UIElement
+
+
+// C# - Saturation can be applied to any UIElement. In this case it is an image called ToolkitLogo.
+using Microsoft.Toolkit.Uwp.UI.Animations;
+
+// Create and attacha a sprite visual with an animatable blur effect
+var sprite = await PipelineBuilder
+ .FromBackdrop()
+ .Saturation(0, out EffectAnimation saturationAnimation)
+ .AttachAsync(ToolkitLogo, ToolkitLogo);
+
+// Start the animation on the applied brush
+saturationAnimation(sprite.Brush, 1, TimeSpan.FromSeconds(3));
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorXaml.bind
new file mode 100644
index 00000000000..bd6836b829f
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/SaturationBehaviorXaml.bind
@@ -0,0 +1,42 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorCode.bind
similarity index 64%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorCode.bind
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorCode.bind
index ebe875e1dca..4b80509233d 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorCode.bind
@@ -4,8 +4,4 @@
// C# - Scale can be applied to any UIElement. In this case it is an image called ToolkitLogo.
using Microsoft.Toolkit.Uwp.UI.Animations;
-await ToolkitLogo.Scale(centerX: 0.5f,
- centerY: 0.0f,
- scaleX: 2.0f,
- scaleY: 0.1f,
- duration: 10, delay: 0).StartAsync();
+await AnimationBuilder.Create().Scale(to: new Vector2(1.4f), duration: TimeSpan.FromSeconds(3)).StartAsync(ToolkitLogo);
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorXaml.bind
new file mode 100644
index 00000000000..acd6ab9b79b
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Behaviors/ScaleBehaviorXaml.bind
@@ -0,0 +1,41 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/EffectAnimations.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/EffectAnimations.bind
new file mode 100644
index 00000000000..1965efbf2b2
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/EffectAnimations.bind
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehavior.png
similarity index 100%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehavior.png
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehavior.png
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorCode.bind
similarity index 64%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorCode.bind
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorCode.bind
index 09ff45a2829..f915f00e0a3 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorCode.bind
@@ -4,5 +4,6 @@
// C# - Fade can be applied to any UIElement. In this case it is an image called ToolkitLogo.
using Microsoft.Toolkit.Uwp.UI.Animations;
-await ToolkitLogo.Fade(value: 0.5f, duration: 10, delay: 0).StartAsync();
+// Create and start the animation
+await AnimationBuilder.Create().Opacity(to: 0.5, duration: TimeSpan.FromSeconds(3)).StartAsync(ToolkitLogo);
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorXaml.bind
new file mode 100644
index 00000000000..1a0f0eb9081
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorXaml.bind
@@ -0,0 +1,36 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorCode.bind
deleted file mode 100644
index b901a0f9cc1..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorCode.bind
+++ /dev/null
@@ -1,8 +0,0 @@
-// XAML UIElement
-
-
-// C# - Blur can be applied to any UIElement. In this case it is an image called ToolkitLogo.
-using Microsoft.Toolkit.Uwp.UI.Animations;
-
-await ToolkitLogo.Blur(value: 10, duration: 10, delay: 0).StartAsync();
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml
deleted file mode 100644
index 8c6ef1f0512..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs
deleted file mode 100644
index 80e76c0dbd2..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the blur behavior.
- ///
- public sealed partial class BlurBehaviorPage : IXamlRenderListener
- {
- private Blur _blurBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public BlurBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _blurBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _blurBehavior = behaviors.FirstOrDefault(item => item is Blur) as Blur;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind
deleted file mode 100644
index a81058031ab..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml
deleted file mode 100644
index 0d85c6bb013..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml.cs
deleted file mode 100644
index 6b6608d7079..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the opacity behavior.
- ///
- public sealed partial class FadeBehaviorPage : Page, IXamlRenderListener
- {
- private Fade _fadeBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public FadeBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _fadeBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _fadeBehavior = behaviors.FirstOrDefault(item => item is Fade) as Fade;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorXaml.bind
deleted file mode 100644
index 2659a3b157a..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Fade/FadeBehaviorXaml.bind
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorPage.xaml
index a2ae6567063..ce25561b9d0 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorPage.xaml
@@ -7,12 +7,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
-
-
-
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorXaml.bind
index 851181f5164..60ffa5965b2 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorXaml.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/FadeHeader/FadeHeaderBehaviorXaml.bind
@@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
- xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Animations.Behaviors"
+ xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
mc:Ignorable="d">
@@ -24,7 +24,7 @@
Margin="12" />
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/IconExtensions/IconExtensionsPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/IconExtensions/IconExtensionsPage.xaml.cs
index 0311ad04acf..35971fb6a53 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/IconExtensions/IconExtensionsPage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/IconExtensions/IconExtensionsPage.xaml.cs
@@ -2,10 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsCode.bind
index 71ab3ffa96e..542f84e2fe3 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsCode.bind
@@ -19,24 +19,24 @@
extensions:VisualExtensions.CenterPoint="50,50,0">
-
-
+
+
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml
index 8ae037ba91f..e9a7b685520 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Implicit Animations/ImplicitAnimationsPage.xaml
@@ -7,29 +7,36 @@
xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions"
xmlns:animations="using:Microsoft.Toolkit.Uwp.UI.Animations"
mc:Ignorable="d">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGrid.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimation.bind
similarity index 90%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGrid.bind
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimation.bind
index 5e1f9a3e0d4..f1e5a995f5e 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGrid.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimation.bind
@@ -9,7 +9,7 @@
+ animations:ItemsReorderAnimation.Duration="@[Duration:TimeSpan:400:0-800]">
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGridPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimationPage.xaml.cs
similarity index 85%
rename from Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGridPage.xaml.cs
rename to Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimationPage.xaml.cs
index dadb81e7ef4..f55559e57b5 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ReorderGridAnimation/ReorderGridPage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ItemsReorderAnimation/ItemsReorderAnimationPage.xaml.cs
@@ -8,11 +8,11 @@
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
- public sealed partial class ReorderGridPage : Page, IXamlRenderListener
+ public sealed partial class ItemsReorderAnimationPage : Page, IXamlRenderListener
{
private GridView imageView;
- public ReorderGridPage()
+ public ItemsReorderAnimationPage()
{
InitializeComponent();
}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehavior.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehavior.png
deleted file mode 100644
index b2235f1b9e4..00000000000
Binary files a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehavior.png and /dev/null differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorCode.bind
deleted file mode 100644
index 4019e9a2ce7..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorCode.bind
+++ /dev/null
@@ -1,8 +0,0 @@
-// XAML UIElement
-
-
-// C# - Light can be applied to any UIElement. In this case it is an image called ToolkitLogo.
-using Microsoft.Toolkit.Uwp.UI.Animations;
-
-var lightAnimationSet = ToolkitLogo.Light(distance: 10, duration: 500, delay: 0, color: Colors.Red);
-await lightAnimationSet.StartAsync();
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml
deleted file mode 100644
index 276a3166388..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml.cs
deleted file mode 100644
index a731da773ad..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the light behavior.
- ///
- public sealed partial class LightBehaviorPage : IXamlRenderListener
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- private Light _lightBehavior;
-#pragma warning restore CS0618 // Type or member is obsolete
-
- ///
- /// Initializes a new instance of the class.
- ///
- public LightBehaviorPage()
- {
- this.InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _lightBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
-#pragma warning disable CS0618 // Type or member is obsolete
- _lightBehavior = behaviors.FirstOrDefault(item => item is Light) as Light;
-#pragma warning restore CS0618 // Type or member is obsolete
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorXaml.bind
deleted file mode 100644
index 2ca51bf1cfc..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Light/LightBehaviorXaml.bind
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LoginButton/LoginButtonPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LoginButton/LoginButtonPage.xaml
index cd37f20d156..ca429d0df3f 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LoginButton/LoginButtonPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LoginButton/LoginButtonPage.xaml
@@ -1,19 +1,19 @@

-
+
-
-
+
+
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorCode.bind
deleted file mode 100644
index 8542d806b02..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorCode.bind
+++ /dev/null
@@ -1,10 +0,0 @@
-// XAML UIElement
-
-
-// C# - Offset can be applied to any UIElement. In this case it is an image called ToolkitLogo.
-using Microsoft.Toolkit.Uwp.UI.Animations;
-
-await ToolkitLogo.Offset(offsetX: 1.0f,
- offsetY: 1.1f,
- duration: 10, delay: 0).StartAsync();
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml
deleted file mode 100644
index 25f1c57dc3c..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml.cs
deleted file mode 100644
index 66b0284957c..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the offset behavior.
- ///
- public sealed partial class OffsetBehaviorPage : IXamlRenderListener
- {
- private Offset _offsetBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public OffsetBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _offsetBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _offsetBehavior = behaviors.FirstOrDefault(item => item is Offset) as Offset;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorXaml.bind
deleted file mode 100644
index 1a1bbb23e30..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Offset/OffsetBehaviorXaml.bind
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OnDevice/OnDevicePage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OnDevice/OnDevicePage.xaml.cs
index 9943ccb283d..274c96025f0 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OnDevice/OnDevicePage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OnDevice/OnDevicePage.xaml.cs
@@ -2,10 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PeoplePicker/PeoplePickerPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PeoplePicker/PeoplePickerPage.xaml
index 829819c6c95..c4da0eaa5ae 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PeoplePicker/PeoplePickerPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PeoplePicker/PeoplePickerPage.xaml
@@ -7,10 +7,12 @@
xmlns:wgt="using:Microsoft.Toolkit.Graph.Controls"
mc:Ignorable="d">
-
+
-
+
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PersonView/PersonViewPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PersonView/PersonViewPage.xaml
index 702efbf97d2..fc19d88e848 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PersonView/PersonViewPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PersonView/PersonViewPage.xaml
@@ -5,8 +5,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wgt="using:Microsoft.Toolkit.Graph.Controls"
mc:Ignorable="d">
-
+
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushPage.xaml
index 7a934c95530..b191e57511f 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushPage.xaml
@@ -1,57 +1,60 @@
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushXaml.bind
index 65233b7e255..e37199d4a34 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushXaml.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PipelineBrush/PipelineBrushXaml.bind
@@ -3,8 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:brushes="using:Microsoft.Toolkit.Uwp.UI.Media"
- xmlns:effects="using:Microsoft.Toolkit.Uwp.UI.Media.Effects"
+ xmlns:media="using:Microsoft.Toolkit.Uwp.UI.Media"
mc:Ignorable="d">
@@ -20,15 +19,15 @@
Grid.Column="2"
Height="400">
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml
deleted file mode 100644
index 7dc91aac97d..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml.cs
deleted file mode 100644
index b814ab90d11..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the Rotation behavior.
- ///
- public sealed partial class RotateBehaviorPage : IXamlRenderListener
- {
- private Rotate _rotateBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public RotateBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _rotateBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _rotateBehavior = behaviors.FirstOrDefault(item => item is Rotate) as Rotate;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorXaml.bind
deleted file mode 100644
index f633e0139da..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Rotate/RotateBehaviorXaml.bind
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorCode.bind
deleted file mode 100644
index e221a771fb0..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorCode.bind
+++ /dev/null
@@ -1,8 +0,0 @@
-// XAML UIElement
-
-
-// C# - Saturation can be applied to any UIElement. In this case it is an image called ToolkitLogo.
-using Microsoft.Toolkit.Uwp.UI.Animations;
-
-await MyImage.Saturation(value: 10, duration: 10, delay: 0).StartAsync();
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml
deleted file mode 100644
index 275c42f1fcd..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml.cs
deleted file mode 100644
index d08eb1c3962..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A demonstration page of how you can use the Saturation effect using behaviors.
- ///
- public sealed partial class SaturationBehaviorPage : IXamlRenderListener
- {
- private Saturation _saturationBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SaturationBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _saturationBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _saturationBehavior = behaviors.FirstOrDefault(item => item is Saturation) as Saturation;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorXaml.bind
deleted file mode 100644
index 8ecf1e81dc4..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Saturation/SaturationBehaviorXaml.bind
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml
deleted file mode 100644
index 74c1d43d6d6..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml.cs
deleted file mode 100644
index 05b27309f49..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorPage.xaml.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.
-
-using System.Linq;
-using Microsoft.Toolkit.Uwp.UI.Animations.Behaviors;
-using Microsoft.Toolkit.Uwp.UI.Extensions;
-using Microsoft.Xaml.Interactivity;
-using Windows.UI.Xaml;
-
-namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
-{
- ///
- /// A page that shows how to use the scale behavior.
- ///
- public sealed partial class ScaleBehaviorPage : IXamlRenderListener
- {
- private Scale _scaleBehavior;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public ScaleBehaviorPage()
- {
- InitializeComponent();
-
- SampleController.Current.RegisterNewCommand("Apply", (s, e) =>
- {
- _scaleBehavior?.StartAnimation();
- });
- }
-
- public void OnXamlRendered(FrameworkElement control)
- {
- if (control.FindChildByName("EffectElement") is FrameworkElement element)
- {
- var behaviors = Interaction.GetBehaviors(element);
- _scaleBehavior = behaviors.FirstOrDefault(item => item is Scale) as Scale;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorXaml.bind
deleted file mode 100644
index 84ee7671e41..00000000000
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Scale/ScaleBehaviorXaml.bind
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderCode.bind
index 8303522e746..9edcd2542b6 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderCode.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderCode.bind
@@ -2,34 +2,37 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:Microsoft.Toolkit.Uwp.SampleApp.Models"
+ xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
+ xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderPage.xaml
index d95346f0b88..44a877fd63d 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader/ScrollHeaderPage.xaml
@@ -1,19 +1,15 @@

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml
index 08bf65c2e7c..d4da6b9a6da 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml
@@ -1,10 +1,12 @@
-
@@ -14,47 +16,49 @@
+ extensions:ScrollViewerExtensions.VerticalScrollBarMargin="{Binding MinHeight, ElementName=MyHeaderGrid, Converter={StaticResource DoubleTopThicknessConverter}}">
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+ Grid.Column="0"
+ Width="100"
+ Height="100"
+ Margin="0,0,24,0"
+ Source="ms-appx:///Assets/ToolkitLogo.png" />
+ VerticalAlignment="Center"
+ Text="{Binding Title}"
+ TextTrimming="CharacterEllipsis" />
@@ -66,45 +70,44 @@
-
-
+
-
-
+ HorizontalAlignment="Center"
+ VerticalAlignment="Center"
+ Orientation="Horizontal"
+ Spacing="4">
+
+
-
-
-
-
+
+
+
+
-
+ Fill="Crimson"
+ Points="0,0 0,60 60,60 60,0"
+ Stroke="DarkRed" />
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml.cs
index 8cea51a5441..3c327b172cf 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsPage.xaml.cs
@@ -4,6 +4,7 @@
using System.Collections.ObjectModel;
using Microsoft.Toolkit.Uwp.SampleApp.Models;
+using Microsoft.Toolkit.Uwp.UI.Animations;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsXaml.bind
index 555377bdebe..6b28c95e185 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsXaml.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollViewerExtensions/ScrollViewerExtensionsXaml.bind
@@ -5,6 +5,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
+ xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
mc:Ignorable="d">
@@ -15,29 +17,30 @@
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ViewportBehavior/ViewportBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ViewportBehavior/ViewportBehaviorPage.xaml.cs
index eb09f531121..7ffbbe7edfe 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ViewportBehavior/ViewportBehaviorPage.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ViewportBehavior/ViewportBehaviorPage.xaml.cs
@@ -6,7 +6,6 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
-using Microsoft.Toolkit.Uwp.UI.Animations;
using Microsoft.Toolkit.Uwp.UI.Behaviors;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Microsoft.Xaml.Interactivity;
@@ -39,7 +38,7 @@ public void OnXamlRendered(FrameworkElement control)
if (control.FindChildByName("EffectElement") is Image effectElement)
{
_effectElement = effectElement;
- _effectElement.Blur(value: 10, duration: 0).Start();
+ ////TODO: _effectElement.Blur(value: 10, duration: 0).Start();
}
if (control.FindChildByName("EffectElementHost") is FrameworkElement effectElementHost)
@@ -72,7 +71,7 @@ private async void EffectElementHost_EnteredViewport(object sender, EventArgs e)
{
AddLog("Entered viewport");
- await _effectElement.Blur(value: 0, duration: 1500).StartAsync();
+ ////TODO: await _effectElement.Blur(value: 0, duration: 1500).StartAsync();
}
private void EffectElementHost_EnteringViewport(object sender, EventArgs e)
@@ -87,7 +86,7 @@ private async void EffectElementHost_ExitedViewport(object sender, EventArgs e)
AddLog("Exited viewport");
_effectElement.Source = null;
- await _effectElement.Blur(value: 8, duration: 0).StartAsync();
+ ////TODO: await _effectElement.Blur(value: 8, duration: 0).StartAsync();
}
private void EffectElementHost_ExitingViewport(object sender, EventArgs e)
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/VisualEffectFactory/VisualEffectFactory.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/VisualEffectFactory/VisualEffectFactory.bind
new file mode 100644
index 00000000000..5bc60f63a37
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/VisualEffectFactory/VisualEffectFactory.bind
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
index decdbe391e9..3b7a093050c 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
@@ -1,9 +1,14 @@

@@ -19,7 +24,36 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
index b7d7a495ffd..5b356756f2d 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
@@ -460,87 +460,84 @@
"Name": "Animations",
"Icon": "Icons/Animations.png",
"Samples": [
+ {
+ "Name": "StartAnimationActivity",
+ "Subcategory": "Activities",
+ "About": "Activity for Animations to Start another Animation",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities",
+ "XamlCodeFile": "/SamplePages/Animations/Activities/StartAnimationActivity.bind",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Fade.md"
+ },
+ {
+ "Name": "InvokeActionsActivity",
+ "Subcategory": "Activities",
+ "About": "Activity chaining Actions from the Behaviors package into an Animation schedule.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations",
+ "XamlCodeFile": "/SamplePages/Animations/Activities/InvokeActionsActivity.bind",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Fade.md"
+ },
{
"Name": "Fade",
- "Type": "FadeBehaviorPage",
- "Subcategory": "Behavior",
- "About": "Opacity of XAML elements using composition",
+ "Subcategory": "Effect",
+ "About": "Opacity of XAML elements using composition animations",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "FadeBehaviorCode.bind",
- "XamlCodeFile": "FadeBehaviorXaml.bind",
- "Icon": "/SamplePages/Fade/FadeBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Effects/FadeBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Effects/FadeBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Effects/FadeBehavior.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Fade.md"
},
{
"Name": "Scale",
- "Type": "ScaleBehaviorPage",
"Subcategory": "Behavior",
"About": "Scale of XAML elements using composition",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "ScaleBehaviorCode.bind",
- "XamlCodeFile": "ScaleBehaviorXaml.bind",
- "Icon": "/SamplePages/Scale/scaleBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Behaviors/ScaleBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Behaviors/ScaleBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Behaviors/ScaleBehavior.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Scale.md"
},
{
"Name": "Offset",
- "Type": "OffsetBehaviorPage",
"Subcategory": "Behavior",
"About": "Offset of XAML elements using composition",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "OffsetBehaviorCode.bind",
- "XamlCodeFile": "OffsetBehaviorXaml.bind",
- "Icon": "/SamplePages/Offset/offsetBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Behaviors/OffsetBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Behaviors/OffsetBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Behaviors/OffsetBehavior.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Offset.md"
},
{
"Name": "Rotate",
- "Type": "RotateBehaviorPage",
"Subcategory": "Behavior",
"About": "Rotation on XAML elements using composition",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "RotateBehaviorCode.bind",
- "XamlCodeFile": "RotateBehaviorXaml.bind",
- "Icon": "/SamplePages/Rotate/rotateBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Behaviors/RotateBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Behaviors/RotateBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Behaviors/RotateBehavior.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Rotate.md"
},
{
"Name": "Blur",
- "Type": "BlurBehaviorPage",
"Subcategory": "Behavior",
"About": "Blur XAML elements using composition",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "BlurBehaviorCode.bind",
- "XamlCodeFile": "BlurBehaviorXaml.bind",
- "Icon": "/SamplePages/Blur/blurBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Behaviors/BlurBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Behaviors/BlurBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Behaviors/BlurBehavior.png",
"BadgeUpdateVersionRequired": "Anniversary Update required",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Blur.md"
},
{
"Name": "Saturation",
- "Type": "SaturationBehaviorPage",
"Subcategory": "Behavior",
"About": "Saturate XAML elements using composition",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "SaturationBehaviorCode.bind",
- "XamlCodeFile": "SaturationBehaviorXaml.bind",
- "Icon": "/SamplePages/Saturation/saturationBehavior.png",
+ "CodeFile": "/SamplePages/Animations/Behaviors/SaturationBehaviorCode.bind",
+ "XamlCodeFile": "/SamplePages/Animations/Behaviors/SaturationBehaviorXaml.bind",
+ "Icon": "/SamplePages/Animations/Behaviors/SaturationBehavior.png",
"BadgeUpdateVersionRequired": "Anniversary Update required",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Saturation.md"
},
- {
- "Name": "Light",
- "Type": "LightBehaviorPage",
- "Subcategory": "Behavior",
- "About": "The Light effect will be removed in a future major release",
- "BadgeUpdateVersionRequired": "DEPRECATED",
- "DeprecatedWarning": "The Light effect will be removed in a future major release",
- "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations/Behaviors",
- "CodeFile": "LightBehaviorCode.bind",
- "XamlCodeFile": "LightBehaviorXaml.bind",
- "Icon": "/SamplePages/Light/LightBehavior.png",
- "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Light.md"
- },
{
"Name": "FadeHeader",
"Type": "FadeHeaderBehaviorPage",
@@ -561,16 +558,24 @@
"CodeUrl": "https://github.com/windows-toolkit/Lottie-Windows"
},
{
- "Name": "ReorderGridAnimation",
- "Type": "ReorderGridPage",
+ "Name": "ItemsReorderAnimation",
+ "Type": "ItemsReorderAnimationPage",
"Subcategory": "Effect",
- "About": "Animates items of a grid when the size changes",
+ "About": "Animates items of a grid or list control when the size changes",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Animations",
- "XamlCodeFile": "ReorderGrid.bind",
- "Icon": "/SamplePages/ReorderGridAnimation/ReorderGrid.png",
+ "XamlCodeFile": "ItemsReorderAnimation.bind",
+ "Icon": "/SamplePages/ItemsReorderAnimation/ItemsReorderAnimation.png",
"BadgeUpdateVersionRequired": "Anniversary Update required",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/ReorderGrid.md"
},
+ {
+ "Name": "EffectAnimations",
+ "Subcategory": "Effect",
+ "About": "Effects from the Media package that can be animated from an AnimationSet schedule.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Media/Animations",
+ "XamlCodeFile": "/SamplePages/Animations/Effects/EffectAnimations.bind",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/Fade.md"
+ },
{
"Name": "Implicit Animations",
"Type": "ImplicitAnimationsPage",
@@ -1111,6 +1116,15 @@
"ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/brushes/PipelineBrush.md"
},
+ {
+ "Name": "VisualEffectFactory",
+ "About": "A composition pipeline which can render any custom Win2D/Composition effects chain directly on a Composition visual.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Media/Brushes/PipelineBrush.cs",
+ "XamlCodeFile": "VisualEffectFactory.bind",
+ "Icon": "/SamplePages/PipelineBrush/PipelineBrush.png",
+ "ApiCheck": "Windows.UI.Xaml.Media.XamlCompositionBrushBase",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/brushes/PipelineBrush.md"
+ },
{
"Name": "AcrylicBrush",
"Type": "AcrylicBrushPage",
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Shell.SamplePicker.cs b/Microsoft.Toolkit.Uwp.SampleApp/Shell.SamplePicker.cs
index b52099921b0..a28da5cbc3e 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Shell.SamplePicker.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Shell.SamplePicker.cs
@@ -221,15 +221,12 @@ private void ContainerItem_Loaded(object sender, RoutedEventArgs e)
{
var staggerDelay = TimeSpan.FromMilliseconds(relativeIndex * 30);
- var animationCollection = new AnimationCollection()
- {
- new OpacityAnimation() { From = 0, To = 1, Duration = TimeSpan.FromMilliseconds(400), Delay = staggerDelay, SetInitialValueBeforeDelay = true },
- new ScaleAnimation() { From = "0.9", To = "1", Duration = TimeSpan.FromMilliseconds(400), Delay = staggerDelay }
- };
-
VisualExtensions.SetNormalizedCenterPoint(itemContainer, "0.5");
- animationCollection.StartAnimation(itemContainer);
+ AnimationBuilder.Create()
+ .Opacity(from: 0, to: 1, delay: staggerDelay)
+ .Scale(from: 0.9, to: 1, delay: staggerDelay)
+ .Start(itemContainer);
}
}
@@ -238,11 +235,8 @@ private void ItemContainer_PointerExited(object sender, Windows.UI.Xaml.Input.Po
var panel = (sender as FrameworkElement).FindDescendant();
if (panel != null)
{
- var animation = new OpacityAnimation() { To = 0, Duration = TimeSpan.FromMilliseconds(1200) };
- animation.StartAnimation(panel);
-
- var parentAnimation = new ScaleAnimation() { To = "1", Duration = TimeSpan.FromMilliseconds(1200) };
- parentAnimation.StartAnimation(panel.Parent as UIElement);
+ AnimationBuilder.Create().Opacity(0, duration: TimeSpan.FromMilliseconds(1200)).Start(panel);
+ AnimationBuilder.Create().Scale(1, duration: TimeSpan.FromMilliseconds(1200)).Start((UIElement)panel.Parent);
}
}
@@ -254,11 +248,9 @@ private void ItemContainer_PointerEntered(object sender, Windows.UI.Xaml.Input.P
if (panel != null)
{
panel.Visibility = Visibility.Visible;
- var animation = new OpacityAnimation() { To = 1, Duration = TimeSpan.FromMilliseconds(600) };
- animation.StartAnimation(panel);
- var parentAnimation = new ScaleAnimation() { To = "1.1", Duration = TimeSpan.FromMilliseconds(600) };
- parentAnimation.StartAnimation(panel.Parent as UIElement);
+ AnimationBuilder.Create().Opacity(1, duration: TimeSpan.FromMilliseconds(600)).Start(panel);
+ AnimationBuilder.Create().Scale(1.1, duration: TimeSpan.FromMilliseconds(600)).Start((UIElement)panel.Parent);
}
}
}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Shell.xaml b/Microsoft.Toolkit.Uwp.SampleApp/Shell.xaml
index 7aa45fcdc86..d878d82ed0c 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Shell.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Shell.xaml
@@ -1,15 +1,14 @@

+ Style="{StaticResource ToolkitNavViewStyle}">
+ QueryIcon="Find"
+ QuerySubmitted="SearchBox_QuerySubmitted"
+ TextChanged="SearchBox_TextChanged" />
-
+
-
-
-
+
+
+
+
+
-
+
-
+
-
+
+ ShadowOpacity="0.7"
+ Color="Black">
-
+
-
+
-
-
-
+
+
-
-
+
+
@@ -125,30 +137,29 @@
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Styles/Custom/PivotHeaderItemUnderlineStyle.xaml b/Microsoft.Toolkit.Uwp.SampleApp/Styles/Custom/PivotHeaderItemUnderlineStyle.xaml
index 73231c861a7..7d7ad535788 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Styles/Custom/PivotHeaderItemUnderlineStyle.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Styles/Custom/PivotHeaderItemUnderlineStyle.xaml
@@ -1,14 +1,17 @@
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -43,71 +79,97 @@
+ Storyboard.TargetProperty="X"
+ To="{ThemeResource PivotHeaderItemLockedTranslation}"
+ Duration="0" />
+ Storyboard.TargetProperty="(UIElement.Opacity)"
+ To="0"
+ Duration="0" />
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -121,25 +183,6 @@
-
-
-
-
-
-
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Styles/Generic.xaml b/Microsoft.Toolkit.Uwp.SampleApp/Styles/Generic.xaml
index a718f6cdf3a..026095d0ae6 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Styles/Generic.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Styles/Generic.xaml
@@ -1,7 +1,6 @@

-
-
-
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSet.cs b/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSet.cs
deleted file mode 100644
index fa8632942f2..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSet.cs
+++ /dev/null
@@ -1,634 +0,0 @@
-// 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.
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Threading.Tasks;
-using Windows.UI.Composition;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Hosting;
-using Windows.UI.Xaml.Media.Animation;
-
-namespace Microsoft.Toolkit.Uwp.UI.Animations
-{
- ///
- /// Defines an object for storing and managing CompositionAnimations for an element
- ///
- public class AnimationSet : IDisposable
- {
- private List _animationSets;
-
- private Compositor _compositor;
- private CompositionScopedBatch _batch;
- private Dictionary _compositionAnimations;
- private List _compositionEffectAnimations;
- private Dictionary _directCompositionPropertyChanges;
- private List _directCompositionEffectPropertyChanges;
-
- private Storyboard _storyboard;
- private Dictionary _storyboardAnimations;
-
- private List _animationTasks;
-
- private TaskCompletionSource _animationTCS;
-
- private bool _storyboardCompleted;
- private bool _compositionCompleted;
-
- ///
- /// Gets or sets a value indicating whether composition must be use even on SDK > 10586
- ///
- public static bool UseComposition { get; set; }
-
- ///
- /// Gets the object that backs the XAML element
- ///
- public Visual Visual { get; private set; }
-
- ///
- /// Gets the
- ///
- public UIElement Element { get; private set; }
-
- ///
- /// Gets the current state of the AnimationSet
- ///
- public AnimationSetState State { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The associated element
- public AnimationSet(UIElement element)
- {
- if (element == null)
- {
- throw new NullReferenceException("Element must not be null");
- }
-
- var visual = ElementCompositionPreview.GetElementVisual(element);
-
- if (visual == null)
- {
- throw new NullReferenceException("Visual must not be null");
- }
-
- Visual = visual;
- if (Visual.Compositor == null)
- {
- throw new NullReferenceException("Visual must have a compositor");
- }
-
- Element = element;
- State = AnimationSetState.NotStarted;
- _compositor = Visual.Compositor;
-
- _compositionAnimations = new Dictionary();
- _compositionEffectAnimations = new List();
- _directCompositionPropertyChanges = new Dictionary();
- _directCompositionEffectPropertyChanges = new List();
- _animationSets = new List();
- _storyboard = new Storyboard();
- _storyboardAnimations = new Dictionary();
- _animationTasks = new List();
- }
-
- ///
- /// Occurs when all animations have completed
- ///
- public event EventHandler Completed;
-
- ///
- /// Stats all animations. This method is not awaitable.
- ///
- public async void Start()
- {
- await StartAsync();
- }
-
- ///
- /// Starts all animations and returns an awaitable task.
- ///
- /// A that can be awaited until all animations have completed
- public async Task StartAsync()
- {
- if (_animationTCS == null || _animationTCS.Task.IsCompleted)
- {
- if (_animationTCS != null && _animationTCS.Task.IsCompleted)
- {
- foreach (var set in _animationSets)
- {
- set.State = AnimationSetState.NotStarted;
- set._animationTCS = null;
- }
- }
-
- State = AnimationSetState.Running;
- _animationTCS = new TaskCompletionSource();
- }
- else
- {
- return await _animationTCS.Task;
- }
-
- foreach (var set in _animationSets)
- {
- if (set.State != AnimationSetState.Completed)
- {
- var completed = await set.StartAsync();
-
- if (!completed)
- {
- // the animation was stopped
- return await _animationTCS.Task;
- }
- }
- }
-
- foreach (var task in _animationTasks)
- {
- if (task.Task != null && !task.Task.IsCompleted)
- {
- await task.Task;
- }
-
- // if _animationSet is stopped while task was running
- if (State == AnimationSetState.Stopped)
- {
- return await _animationTCS.Task;
- }
- }
-
- _animationTasks.Clear();
-
- foreach (var property in _directCompositionPropertyChanges)
- {
- typeof(Visual).GetProperty(property.Key).SetValue(Visual, property.Value);
- }
-
- foreach (var definition in _directCompositionEffectPropertyChanges)
- {
- definition.EffectBrush.Properties.InsertScalar(definition.PropertyName, definition.Value);
- }
-
- if (_compositionAnimations.Count > 0 || _compositionEffectAnimations.Count > 0)
- {
- if (_batch != null)
- {
- if (!_batch.IsEnded)
- {
- _batch.End();
- }
-
- _batch.Completed -= Batch_Completed;
- }
-
- _batch = _compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
- _batch.Completed += Batch_Completed;
-
- foreach (var anim in _compositionAnimations)
- {
- Visual.StartAnimation(anim.Key, anim.Value);
- }
-
- foreach (var effect in _compositionEffectAnimations)
- {
- effect.EffectBrush.StartAnimation(effect.PropertyName, effect.Animation);
- }
-
- _compositionCompleted = false;
- _batch.End();
- }
- else
- {
- _compositionCompleted = true;
- }
-
- if (_storyboardAnimations.Count > 0)
- {
- _storyboardCompleted = false;
-
- _storyboard.Completed -= Storyboard_Completed;
- _storyboard.Completed += Storyboard_Completed;
-
- _storyboard.Begin();
- }
- else
- {
- _storyboardCompleted = true;
- }
-
- HandleCompleted();
-
- return await _animationTCS.Task;
- }
-
- ///
- /// Stops all animations.
- ///
- public void Stop()
- {
- foreach (var set in _animationSets)
- {
- if (set.State != AnimationSetState.Completed)
- {
- set.Stop();
- }
- }
-
- if (_batch != null)
- {
- if (!_batch.IsEnded)
- {
- _batch.End();
- }
-
- _batch.Completed -= Batch_Completed;
- }
-
- foreach (var anim in _compositionAnimations)
- {
- Visual.StopAnimation(anim.Key);
- }
-
- foreach (var effect in _compositionEffectAnimations)
- {
- effect.EffectBrush.StopAnimation(effect.PropertyName);
- }
-
- _storyboard.Pause();
-
- HandleCompleted(true);
- _animationTCS = null;
- }
-
- ///
- /// Wait for existing animations to complete before running new animations
- ///
- /// AnimationSet to allow chaining
- public AnimationSet Then()
- {
- var savedAnimationSet = new AnimationSet(Element);
- savedAnimationSet._compositionAnimations = _compositionAnimations;
- savedAnimationSet._compositionEffectAnimations = _compositionEffectAnimations;
- savedAnimationSet._directCompositionPropertyChanges = _directCompositionPropertyChanges;
- savedAnimationSet._directCompositionEffectPropertyChanges = _directCompositionEffectPropertyChanges;
- savedAnimationSet._storyboard = _storyboard;
- savedAnimationSet._storyboardAnimations = _storyboardAnimations;
-
- _animationTasks.ForEach(t => t.AnimationSet = savedAnimationSet);
- savedAnimationSet._animationTasks = _animationTasks;
-
- _animationSets.Add(savedAnimationSet);
-
- _compositionAnimations = new Dictionary();
- _compositionEffectAnimations = new List();
- _directCompositionPropertyChanges = new Dictionary();
- _directCompositionEffectPropertyChanges = new List();
- _storyboard = new Storyboard();
- _storyboardAnimations = new Dictionary();
- _animationTasks = new List();
-
- return this;
- }
-
- ///
- /// Overwrites the duration on all animations after last Then()
- /// to the specified value
- ///
- /// The duration in milliseconds
- /// AnimationSet to allow chaining
- public AnimationSet SetDuration(double duration)
- {
- if (duration <= 0)
- {
- duration = 1;
- }
-
- return SetDuration(TimeSpan.FromMilliseconds(duration));
- }
-
- ///
- /// Overwrites the duration on all animations after last Then()
- /// to the specified value
- ///
- /// for the duration
- /// AnimationSet to allow chaining
- public AnimationSet SetDuration(TimeSpan duration)
- {
- foreach (var task in _animationTasks)
- {
- task.Duration = duration;
- }
-
- foreach (var anim in _compositionAnimations)
- {
- var animation = anim.Value as KeyFrameAnimation;
- if (animation != null)
- {
- animation.Duration = duration;
- }
- }
-
- foreach (var effect in _compositionEffectAnimations)
- {
- var animation = effect.Animation as KeyFrameAnimation;
- if (animation != null)
- {
- animation.Duration = duration;
- }
- }
-
- foreach (var timeline in _storyboardAnimations)
- {
- var animation = timeline.Value as DoubleAnimation;
- if (animation != null)
- {
- animation.Duration = duration;
- }
- }
-
- return this;
- }
-
- ///
- /// Overwrites the duration on all animations to the specified value
- ///
- /// The duration in milliseconds
- /// AnimationSet to allow chaining
- public AnimationSet SetDurationForAll(double duration)
- {
- foreach (var set in _animationSets)
- {
- set.SetDuration(duration);
- }
-
- return SetDuration(duration);
- }
-
- ///
- /// Overwrites the duration on all animations to the specified value
- ///
- /// for the duration
- /// AnimationSet to allow chaining
- public AnimationSet SetDurationForAll(TimeSpan duration)
- {
- foreach (var set in _animationSets)
- {
- set.SetDuration(duration);
- }
-
- return SetDuration(duration);
- }
-
- ///
- /// Overwrites the delay time on all animations after last Then()
- /// to the specified value
- ///
- /// The delay time in milliseconds
- /// AnimationSet to allow chaining
- public AnimationSet SetDelay(double delayTime)
- {
- if (delayTime < 0)
- {
- delayTime = 0;
- }
-
- return SetDelay(TimeSpan.FromMilliseconds(delayTime));
- }
-
- ///
- /// Overwrites the delay time on all animations after last Then()
- /// to the specified value
- ///
- /// for how much to delay
- /// AnimationSet to allow chaining
- public AnimationSet SetDelay(TimeSpan delayTime)
- {
- foreach (var task in _animationTasks)
- {
- task.Delay = delayTime;
- }
-
- foreach (var anim in _compositionAnimations)
- {
- var animation = anim.Value as KeyFrameAnimation;
- if (animation != null)
- {
- animation.DelayTime = delayTime;
- }
- }
-
- foreach (var effect in _compositionEffectAnimations)
- {
- var animation = effect.Animation as KeyFrameAnimation;
- if (animation != null)
- {
- animation.DelayTime = delayTime;
- }
- }
-
- foreach (var timeline in _storyboardAnimations)
- {
- var animation = timeline.Value as DoubleAnimation;
- if (animation != null)
- {
- animation.BeginTime = delayTime;
- }
- }
-
- return this;
- }
-
- ///
- /// Overwrites the delay time on all animations to the specified value
- ///
- /// The delay time in milliseconds
- /// AnimationSet to allow chaining
- public AnimationSet SetDelayForAll(double delayTime)
- {
- foreach (var set in _animationSets)
- {
- set.SetDelay(delayTime);
- }
-
- return SetDelay(delayTime);
- }
-
- ///
- /// Overwrites the delay time on all animations to the specified value
- ///
- /// for how much to delay
- /// AnimationSet to allow chaining
- public AnimationSet SetDelayForAll(TimeSpan delayTime)
- {
- foreach (var set in _animationSets)
- {
- set.SetDelay(delayTime);
- }
-
- return SetDelay(delayTime);
- }
-
- ///
- /// Adds a composition animation to be run on
- ///
- /// The property to be animated on the backing Visual
- /// The to be applied
- public void AddCompositionAnimation(string propertyName, CompositionAnimation animation)
- {
- _compositionAnimations[propertyName] = animation;
- }
-
- ///
- /// Removes a composition animation from being run on property
- ///
- /// The property that no longer needs to be animated
- public void RemoveCompositionAnimation(string propertyName)
- {
- if (_compositionAnimations.ContainsKey(propertyName))
- {
- _compositionAnimations.Remove(propertyName);
- }
- }
-
- ///
- /// Adds a composition effect animation to be run on backing
- ///
- /// The that will have a property animated
- /// The animation to be applied
- /// The property of the effect to be animated
- public void AddCompositionEffectAnimation(CompositionObject effectBrush, CompositionAnimation animation, string propertyName)
- {
- var effect = new EffectAnimationDefinition()
- {
- EffectBrush = effectBrush,
- Animation = animation,
- PropertyName = propertyName
- };
-
- _compositionEffectAnimations.Add(effect);
- }
-
- ///
- /// Adds a composition property that will change instantaneously
- ///
- /// The property to be animated on the backing Visual
- /// The value to be applied
- public void AddCompositionDirectPropertyChange(string propertyName, object value)
- {
- _directCompositionPropertyChanges[propertyName] = value;
- }
-
- ///
- /// Removes a composition property change
- ///
- /// The property that no longer needs to be changed
- public void RemoveCompositionDirectPropertyChange(string propertyName)
- {
- if (_directCompositionPropertyChanges.ContainsKey(propertyName))
- {
- _directCompositionPropertyChanges.Remove(propertyName);
- }
- }
-
- ///
- /// Adds a storyboard animation to be run
- ///
- /// The property to be animated with Storyboards
- /// The timeline object to be added to storyboard
- public void AddStoryboardAnimation(string propertyPath, Timeline timeline)
- {
- if (_storyboardAnimations.ContainsKey(propertyPath))
- {
- var previousAnimation = _storyboardAnimations[propertyPath];
- _storyboard.Children.Remove(previousAnimation);
- _storyboardAnimations.Remove(propertyPath);
- }
-
- _storyboardAnimations.Add(propertyPath, timeline);
- _storyboard.Children.Add(timeline);
-
- Storyboard.SetTarget(timeline, Element);
- Storyboard.SetTargetProperty(timeline, propertyPath);
- }
-
- ///
- /// Dispose resources.
- ///
- public void Dispose()
- {
- _animationTCS = null;
- }
-
- ///
- /// Adds a to the AnimationSet that
- /// will run add an animation once completed. Useful when an animation
- /// needs to do asynchronous initialization before running
- ///
- /// The to be added
- internal void AddAnimationThroughTask(AnimationTask animationTask)
- {
- _animationTasks.Add(animationTask);
- }
-
- ///
- /// Adds an effect property change to be run on
- ///
- /// The that will have a property changed
- /// The value to be applied
- /// The property of the effect to be animated
- internal void AddEffectDirectPropertyChange(CompositionObject effectBrush, float value, string propertyName)
- {
- var definition = new EffectDirectPropertyChangeDefinition()
- {
- EffectBrush = effectBrush,
- Value = value,
- PropertyName = propertyName
- };
-
- _directCompositionEffectPropertyChanges.Add(definition);
- }
-
- private void Storyboard_Completed(object sender, object e)
- {
- _storyboardCompleted = true;
- _storyboard.Completed -= Storyboard_Completed;
- HandleCompleted();
- }
-
- private void Batch_Completed(object sender, CompositionBatchCompletedEventArgs args)
- {
- _compositionCompleted = true;
- _batch.Completed -= Batch_Completed;
- HandleCompleted();
- }
-
- private void HandleCompleted(bool stopped = false)
- {
- var completed = _storyboardCompleted && _compositionCompleted;
-
- if (!completed && !stopped)
- {
- return;
- }
-
- if (_storyboardCompleted && _compositionCompleted)
- {
- State = AnimationSetState.Completed;
- }
- else
- {
- State = AnimationSetState.Stopped;
- }
-
- if (_animationTCS != null && !_animationTCS.Task.IsCompleted)
- {
- _animationTCS.SetResult(State == AnimationSetState.Completed);
- Completed?.Invoke(this, new AnimationSetCompletedEventArgs() { Completed = _storyboardCompleted && _compositionCompleted });
- }
- }
- }
-}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetCompletedEventArgs.cs b/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetCompletedEventArgs.cs
deleted file mode 100644
index 3bad5d6cb13..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetCompletedEventArgs.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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.
-
-using System;
-
-namespace Microsoft.Toolkit.Uwp.UI.Animations
-{
- ///
- /// AnimationSet Completed EventArgs.
- ///
- public class AnimationSetCompletedEventArgs : EventArgs
- {
- ///
- /// Gets a value indicating whether the animation completed
- ///
- public bool Completed { get; internal set; }
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetState.cs b/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetState.cs
deleted file mode 100644
index 9157c72c0f2..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationSetState.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-namespace Microsoft.Toolkit.Uwp.UI.Animations
-{
- ///
- /// States of AnimationSet.
- ///
- public enum AnimationSetState
- {
- ///
- /// The animation has not been started
- ///
- NotStarted,
-
- ///
- /// The animation has been started and is in progress
- ///
- Running,
-
- ///
- /// The animation has been started and is stopped
- ///
- Stopped,
-
- ///
- /// The animation had completed
- ///
- Completed
- }
-}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationTask.cs b/Microsoft.Toolkit.Uwp.UI.Animations/AnimationTask.cs
deleted file mode 100644
index d9aefee2beb..00000000000
--- a/Microsoft.Toolkit.Uwp.UI.Animations/AnimationTask.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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.
-
-using System;
-using System.Threading.Tasks;
-
-namespace Microsoft.Toolkit.Uwp.UI.Animations
-{
- ///
- /// Defines which is used by
- /// to run animations that require
- /// asynchronous initialization
- ///
- internal class AnimationTask
- {
- ///
- /// Gets or sets that will run before any animation
- /// and it will add the animation to the AnimationSet once complete
- ///
- public Task Task { get; set; }
-
- ///
- /// Gets or sets that will run the animation
- ///
- public AnimationSet AnimationSet { get; set; }
-
- ///
- /// Gets or sets Duration to be applied to the animation once the task is completed
- /// Used when Duration is changed before Task completes
- ///
- public TimeSpan? Duration { get; set; }
-
- ///
- /// Gets or sets Delay to be applied to the animation once the task is completed
- /// Used when Duration is changed before Task completes
- ///
- public TimeSpan? Delay { get; set; }
- }
-}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs
new file mode 100644
index 00000000000..5e15a7de772
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs
@@ -0,0 +1,794 @@
+// 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.
+
+#nullable enable
+
+using System;
+using System.Numerics;
+using Microsoft.Toolkit.Diagnostics;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// Adds a new anchor point animation for a single axis to the current schedule.
+ ///
+ /// The target anchor point axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder AnchorPoint(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.AnchorPoint(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new anchor point animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder AnchorPoint(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ AddCompositionAnimationFactory(nameof(Visual.AnchorPoint), to, from, delay, duration, easingType, easingMode);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new opacity animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Opacity(
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(nameof(Visual.Opacity), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlAnimationFactory(nameof(UIElement.Opacity), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new translation animation for a single axis to the current schedule.
+ ///
+ /// The target translation axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Translation(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.Translation(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlAnimationFactory(Properties.Xaml.Translation(axis), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new translation animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Translation(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.TranslationXY(), to, from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.TranslateX), to.X, from?.X, delay, duration, easingType, easingMode);
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.TranslateY), to.Y, from?.Y, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new composition translation animation for all axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Translation(
+ Vector3 to,
+ Vector3? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(Properties.Composition.Translation(), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new composition offset animation for a single axis to the current schedule.
+ ///
+ /// The target translation axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Offset(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(Properties.Composition.Offset(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new composition offset animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Offset(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.OffsetXY(), to, from, delay, duration, easingType, easingMode);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new composition offset translation animation for all axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Offset(
+ Vector3 to,
+ Vector3? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(nameof(Visual.Offset), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new uniform scale animation for all axes to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Scale(
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ Vector3? from3 = from is null ? null : new((float)(double)from);
+ Vector3 to3 = new((float)to);
+
+ AddCompositionAnimationFactory(nameof(Visual.Scale), to3, from3, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.ScaleX), to, from, delay, duration, easingType, easingMode);
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.ScaleY), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new scale animation on a specified axis to the current schedule.
+ ///
+ /// The target scale axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Scale(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.Scale(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(Properties.Xaml.Scale(axis), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new scale animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Scale(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.ScaleXY(), to, from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.ScaleX), to.X, from?.X, delay, duration, easingType, easingMode);
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.ScaleY), to.Y, from?.Y, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new scale animation for all axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Scale(
+ Vector3 to,
+ Vector3? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(nameof(Visual.Scale), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new center point animation on a specified axis to the current schedule.
+ ///
+ /// The target scale axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder CenterPoint(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.CenterPoint(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(Properties.Xaml.CenterPoint(axis), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new center point animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder CenterPoint(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.CenterPointXY(), to, from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.CenterX), to.X, from?.X, delay, duration, easingType, easingMode);
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.CenterY), to.Y, from?.Y, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new center point animation for all axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder CenterPoint(
+ Vector3 to,
+ Vector3? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(nameof(Visual.CenterPoint), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new rotation animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Rotation(
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(nameof(Visual.RotationAngle), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ double? fromDegrees = from * Math.PI / 180;
+ double toDegrees = to * Math.PI / 180;
+
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.Rotation), toDegrees, fromDegrees, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new rotation animation in degrees to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder RotationInDegrees(
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(nameof(Visual.RotationAngleInDegrees), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlTransformDoubleAnimationFactory(nameof(CompositeTransform.Rotation), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new rotation axis animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder RotationAxis(
+ Vector3 to,
+ Vector3? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(nameof(Visual.RotationAxis), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new orientation animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Orientation(
+ Quaternion to,
+ Quaternion? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ return AddCompositionAnimationFactory(nameof(Visual.Orientation), to, from, delay, duration, easingType, easingMode);
+ }
+
+ ///
+ /// Adds a new transform animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Transform(
+ Matrix4x4 to,
+ Matrix4x4? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ if (!Matrix4x4.Decompose(to, out Vector3 toScale, out Quaternion toRotation, out Vector3 toTranslation))
+ {
+ ThrowHelper.ThrowArgumentException("The destination matrix could not be decomposed");
+ }
+
+ Vector3? fromScale = null;
+ Quaternion? fromRotation = null;
+ Vector3? fromTranslation = null;
+
+ if (from.HasValue)
+ {
+ if (!Matrix4x4.Decompose(from.GetValueOrDefault(), out Vector3 scale3, out Quaternion rotation4, out Vector3 translation3))
+ {
+ ThrowHelper.ThrowArgumentException("The initial matrix could not be decomposed");
+ }
+
+ fromScale = scale3;
+ fromRotation = rotation4;
+ fromTranslation = translation3;
+ }
+
+ Scale(toScale, fromScale, delay, duration, easingType, easingMode);
+ Orientation(toRotation, fromRotation, delay, duration, easingType, easingMode);
+ Translation(toTranslation, fromTranslation, delay, duration, easingType, easingMode);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new clip animation to the current schedule.
+ ///
+ /// The clip size to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Clip(
+ Side side,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ CompositionClipScalarAnimation animation = new(
+ Properties.Composition.Clip(side),
+ (float)to,
+ (float?)from,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode);
+
+ this.compositionAnimationFactories.Add(animation);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new clip animation to the current schedule.
+ ///
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The current instance.
+ /// This animation is only available on the composition layer.
+ public AnimationBuilder Clip(
+ Thickness to,
+ Thickness? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode)
+ {
+ this.compositionAnimationFactories.Add(new CompositionClipScalarAnimation(
+ nameof(InsetClip.LeftInset),
+ (float)to.Left,
+ (float?)from?.Left,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode));
+
+ this.compositionAnimationFactories.Add(new CompositionClipScalarAnimation(
+ nameof(InsetClip.TopInset),
+ (float)to.Top,
+ (float?)from?.Top,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode));
+
+ this.compositionAnimationFactories.Add(new CompositionClipScalarAnimation(
+ nameof(InsetClip.RightInset),
+ (float)to.Right,
+ (float?)from?.Right,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode));
+
+ this.compositionAnimationFactories.Add(new CompositionClipScalarAnimation(
+ nameof(InsetClip.BottomInset),
+ (float)to.Bottom,
+ (float?)from?.Bottom,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode));
+
+ return this;
+ }
+
+ ///
+ /// Adds a new size animation for a single axis to the current schedule.
+ ///
+ /// The target size axis to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Size(
+ Axis axis,
+ double to,
+ double? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.Size(axis), (float)to, (float?)from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlAnimationFactory(Properties.Xaml.Size(axis), to, from, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a new size animation for the X and Y axes to the current schedule.
+ ///
+ /// The final point for the animation.
+ /// The optional starting point for the animation.
+ /// The optional initial delay for the animation.
+ /// The optional animation duration.
+ /// The optional easing function type for the animation.
+ /// The optional easing function mode for the animation.
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder Size(
+ Vector2 to,
+ Vector2? from = null,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ EasingType easingType = DefaultEasingType,
+ EasingMode easingMode = DefaultEasingMode,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ AddCompositionAnimationFactory(Properties.Composition.Size(), to, from, delay, duration, easingType, easingMode);
+ }
+ else
+ {
+ AddXamlAnimationFactory(nameof(FrameworkElement.Width), to.X, from?.X, delay, duration, easingType, easingMode);
+ AddXamlAnimationFactory(nameof(FrameworkElement.Height), to.Y, from?.Y, delay, duration, easingType, easingMode);
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.External.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.External.cs
new file mode 100644
index 00000000000..68dd890babd
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.External.cs
@@ -0,0 +1,55 @@
+// 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.
+
+#nullable enable
+
+using Windows.UI.Composition;
+using Windows.UI.Xaml.Media.Animation;
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// Adds a new external animation to the current schedule, which will be executed on the same
+ /// target object the current instance will be invoked upon.
+ ///
+ /// The external instance to add to the schedule.
+ /// The current instance.
+ public AnimationBuilder ExternalAnimation(CompositionAnimation animation)
+ {
+ this.compositionAnimationFactories.Add(new ExternalCompositionAnimation(null, animation));
+
+ return this;
+ }
+
+ ///
+ /// Adds a new external animation to the current schedule, which will be executed on a given
+ /// when the current instance is invoked.
+ ///
+ /// The target to invoke the animation upon.
+ /// The external instance to add to the schedule.
+ /// The current instance.
+ public AnimationBuilder ExternalAnimation(CompositionObject target, CompositionAnimation animation)
+ {
+ this.compositionAnimationFactories.Add(new ExternalCompositionAnimation(target, animation));
+
+ return this;
+ }
+
+ ///
+ /// Adds a new external animation to the current schedule, which will be executed on the same
+ /// target object the current instance will be invoked upon.
+ ///
+ /// The external instance to add to the schedule.
+ /// The current instance.
+ public AnimationBuilder ExternalAnimation(Timeline animation)
+ {
+ this.xamlAnimationFactories.Add(new ExternalXamlAnimation(animation));
+
+ return this;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs
new file mode 100644
index 00000000000..455603b2aea
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs
@@ -0,0 +1,338 @@
+// 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.
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using Microsoft.Toolkit.Diagnostics;
+using Windows.Foundation;
+using Windows.UI;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+
+#nullable enable
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// An interface for factories of XAML animations.
+ ///
+ internal interface IXamlAnimationFactory
+ {
+ ///
+ /// Gets a instance representing the animation to start.
+ ///
+ /// The suggested target instance to animate.
+ /// A instance with the specified animation.
+ Timeline GetAnimation(DependencyObject targetHint);
+ }
+
+ ///
+ /// An interface for factories of composition animations.
+ ///
+ internal interface ICompositionAnimationFactory
+ {
+ ///
+ /// Gets a instance representing the animation to start.
+ ///
+ /// The suggested target instance to animate.
+ /// An optional instance to animate instead of the suggested one.
+ /// A instance with the specified animation.
+ ///
+ /// The separate parameter is needed because unlike with XAML animations, composition animations
+ /// can't store the target instance internally, and need to be started on the target object directly. This means that custom
+ /// animation factories that want to target an external object need to return that object separately to inform the callers.
+ ///
+ CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target);
+ }
+
+ ///
+ /// A model representing a generic animation for a target object.
+ ///
+ private sealed record AnimationFactory(
+ string Property,
+ T To,
+ T? From,
+ TimeSpan Delay,
+ TimeSpan Duration,
+ EasingType EasingType,
+ EasingMode EasingMode)
+ : ICompositionAnimationFactory, IXamlAnimationFactory
+ where T : unmanaged
+ {
+ ///
+ public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
+ {
+ CompositionEasingFunction? easingFunction = targetHint.Compositor.TryCreateEasingFunction(EasingType, EasingMode);
+
+ target = null;
+
+ if (typeof(T) == typeof(bool))
+ {
+ return targetHint.Compositor.CreateBooleanKeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration);
+ }
+
+ if (typeof(T) == typeof(float))
+ {
+ return targetHint.Compositor.CreateScalarKeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ return targetHint.Compositor.CreateScalarKeyFrameAnimation(
+ Property,
+ (float)GetToAs(),
+ (float?)GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(Vector2))
+ {
+ return targetHint.Compositor.CreateVector2KeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(Vector3))
+ {
+ return targetHint.Compositor.CreateVector3KeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(Vector4))
+ {
+ return targetHint.Compositor.CreateVector4KeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(Color))
+ {
+ return targetHint.Compositor.CreateColorKeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ if (typeof(T) == typeof(Quaternion))
+ {
+ return targetHint.Compositor.CreateQuaternionKeyFrameAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ return ThrowHelper.ThrowInvalidOperationException("Invalid animation type");
+ }
+
+ ///
+ public Timeline GetAnimation(DependencyObject targetHint)
+ {
+ EasingFunctionBase? easingFunction = EasingType.ToEasingFunction(EasingMode);
+
+ if (typeof(T) == typeof(float))
+ {
+ return targetHint.CreateDoubleAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction,
+ enableDependecyAnimations: true);
+ }
+
+ if (typeof(T) == typeof(double))
+ {
+ return targetHint.CreateDoubleAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction,
+ enableDependecyAnimations: true);
+ }
+
+ if (typeof(T) == typeof(Point))
+ {
+ return targetHint.CreatePointAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction,
+ enableDependecyAnimations: true);
+ }
+
+ if (typeof(T) == typeof(Color))
+ {
+ return targetHint.CreateColorAnimation(
+ Property,
+ GetToAs(),
+ GetFromAs(),
+ Delay,
+ Duration,
+ easingFunction);
+ }
+
+ return ThrowHelper.ThrowInvalidOperationException("Invalid animation type");
+ }
+
+ ///
+ /// Gets the current target value as .
+ ///
+ /// The target value type to use.
+ /// The target type cast to .
+ [Pure]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private TValue GetToAs()
+ where TValue : unmanaged
+ {
+ T to = To;
+
+ return Unsafe.As(ref to);
+ }
+
+ ///
+ /// Gets the current starting value as .
+ ///
+ /// The starting value type to use.
+ /// The starting type cast to nullable .
+ [Pure]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private TValue? GetFromAs()
+ where TValue : unmanaged
+ {
+ if (From is null)
+ {
+ return null;
+ }
+
+ T from = From.GetValueOrDefault();
+
+ return Unsafe.As(ref from);
+ }
+ }
+
+ ///
+ /// A model representing a specified composition scalar animation factory targeting a clip.
+ ///
+ private sealed record CompositionClipScalarAnimation(
+ string Property,
+ float To,
+ float? From,
+ TimeSpan Delay,
+ TimeSpan Duration,
+ EasingType EasingType,
+ EasingMode EasingMode)
+ : ICompositionAnimationFactory
+ {
+ ///
+ public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
+ {
+ Visual visual = (Visual)targetHint;
+ InsetClip clip = visual.Clip as InsetClip ?? (InsetClip)(visual.Clip = visual.Compositor.CreateInsetClip());
+ CompositionEasingFunction? easingFunction = clip.Compositor.TryCreateEasingFunction(EasingType, EasingMode);
+ ScalarKeyFrameAnimation animation = clip.Compositor.CreateScalarKeyFrameAnimation(Property, To, From, Delay, Duration, easingFunction);
+
+ target = clip;
+
+ return animation;
+ }
+ }
+
+ ///
+ /// A model representing a specified XAML animation factory targeting a transform.
+ ///
+ private sealed record XamlTransformDoubleAnimationFactory(
+ string Property,
+ double To,
+ double? From,
+ TimeSpan Delay,
+ TimeSpan Duration,
+ EasingType EasingType,
+ EasingMode EasingMode)
+ : IXamlAnimationFactory
+ {
+ ///
+ public Timeline GetAnimation(DependencyObject targetHint)
+ {
+ UIElement element = (UIElement)targetHint;
+
+ if (element.RenderTransform is not CompositeTransform transform)
+ {
+ element.RenderTransform = transform = new CompositeTransform();
+ }
+
+ return transform.CreateDoubleAnimation(Property, To, From, Duration, Delay, EasingType.ToEasingFunction(EasingMode));
+ }
+ }
+
+ ///
+ /// A model representing an external composition animation with an optional target .
+ ///
+ private sealed record ExternalCompositionAnimation(CompositionObject? Target, CompositionAnimation Animation) : ICompositionAnimationFactory
+ {
+ ///
+ public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
+ {
+ target = Target;
+
+ return Animation;
+ }
+ }
+
+ ///
+ /// A model representing an external composition animation with an optional target .
+ ///
+ private sealed record ExternalXamlAnimation(Timeline Animation) : IXamlAnimationFactory
+ {
+ ///
+ public Timeline GetAnimation(DependencyObject targetHint)
+ {
+ return Animation;
+ }
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.KeyFrames.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.KeyFrames.cs
new file mode 100644
index 00000000000..e349a62c50c
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.KeyFrames.cs
@@ -0,0 +1,408 @@
+// 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.
+
+#nullable enable
+
+using System;
+using System.Numerics;
+using Windows.UI.Composition;
+using Windows.UI.Xaml.Media;
+using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// Adds a new anchor point animation for a single axis to the current schedule.
+ ///
+ /// The target anchor point axis to animate.
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder AnchorPoint(Axis axis)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.AnchorPoint(axis), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new anchor point animation for the X and Y axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder AnchorPoint()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.AnchorPoint), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new opacity animation to the current schedule.
+ ///
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder Opacity(FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.Opacity), layer);
+ }
+
+ ///
+ /// Adds a new translation animation for a single axis to the current schedule.
+ ///
+ /// The target translation axis to animate.
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder Translation(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.Translation(axis), layer);
+ }
+
+ return new XamlTransformPropertyAnimationBuilder(this, Properties.Xaml.Translation(axis));
+ }
+
+ ///
+ /// Adds a new composition translation animation for all axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Translation()
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.Translation(), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new composition offset animation for a single axis to the current schedule.
+ ///
+ /// The target translation axis to animate.
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Offset(Axis axis)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.Offset(axis), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new composition offset translation animation for all axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Offset()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.Offset), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new scale animation on a specified axis to the current schedule.
+ ///
+ /// The target scale axis to animate.
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder Scale(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.Scale(axis), layer);
+ }
+
+ return new XamlTransformPropertyAnimationBuilder(this, Properties.Xaml.Scale(axis));
+ }
+
+ ///
+ /// Adds a new scale animation for all axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Scale()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.Scale), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new center point animation on a specified axis to the current schedule.
+ ///
+ /// The target scale axis to animate.
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder CenterPoint(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.CenterPoint(axis), layer);
+ }
+
+ return new XamlTransformPropertyAnimationBuilder(this, Properties.Xaml.CenterPoint(axis));
+ }
+
+ ///
+ /// Adds a new center point animation for all axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder CenterPoint()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.CenterPoint), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new rotation animation to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Rotation()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.RotationAngle), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new rotation animation in degrees to the current schedule.
+ ///
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder RotationInDegrees(FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.RotationAngleInDegrees), layer);
+ }
+
+ return new XamlTransformPropertyAnimationBuilder(this, nameof(CompositeTransform.Rotation));
+ }
+
+ ///
+ /// Adds a new rotation axis animation to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder RotationAxis()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.RotationAxis), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new orientation animation to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Orientation()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.Orientation), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a new clip animation to the current schedule.
+ ///
+ /// The clip size to animate.
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Clip(Side side)
+ {
+ return new CompositionClipAnimationBuilder(this, Properties.Composition.Clip(side));
+ }
+
+ ///
+ /// Adds a new size animation for a single axis to the current schedule.
+ ///
+ /// The target size axis to animate.
+ /// The target framework layer to animate.
+ /// An instance to configure the animation.
+ public IPropertyAnimationBuilder Size(Axis axis, FrameworkLayer layer = FrameworkLayer.Composition)
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ return new PropertyAnimationBuilder(this, Properties.Composition.Size(axis), layer);
+ }
+
+ return new PropertyAnimationBuilder(this, Properties.Xaml.Size(axis), layer);
+ }
+
+ ///
+ /// Adds a new composition size translation animation for all axes to the current schedule.
+ ///
+ /// An instance to configure the animation.
+ /// This animation is only available on the composition layer.
+ public IPropertyAnimationBuilder Size()
+ {
+ return new PropertyAnimationBuilder(this, nameof(Visual.Size), FrameworkLayer.Composition);
+ }
+
+ ///
+ /// Adds a custom animation based on normalized keyframes to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The target property to animate.
+ /// The callback to use to construct the custom animation.
+ /// The optional initial delay for the animation.
+ /// The animation duration.
+ /// The repeat option for the animation (defaults to one iteration).
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder NormalizedKeyFrames(
+ string property,
+ Action> build,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ RepeatOption? repeatOption = null,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ where T : unmanaged
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ NormalizedKeyFrameAnimationBuilder.Composition builder = new(
+ property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ this.compositionAnimationFactories.Add(builder);
+ }
+ else
+ {
+ NormalizedKeyFrameAnimationBuilder.Xaml builder = new(
+ property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ this.xamlAnimationFactories.Add(builder);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a custom animation based on normalized keyframes to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The type of state to pass to the builder.
+ /// The target property to animate.
+ /// The state to pass to the builder.
+ /// The callback to use to construct the custom animation.
+ /// The optional initial delay for the animation.
+ /// The animation duration.
+ /// The repeat option for the animation (defaults to one iteration).
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder NormalizedKeyFrames(
+ string property,
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay = null,
+ TimeSpan? duration = null,
+ RepeatOption? repeatOption = null,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ where T : unmanaged
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ NormalizedKeyFrameAnimationBuilder.Composition builder = new(
+ property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ this.compositionAnimationFactories.Add(builder);
+ }
+ else
+ {
+ NormalizedKeyFrameAnimationBuilder.Xaml builder = new(
+ property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ this.xamlAnimationFactories.Add(builder);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a custom animation based on timed keyframes to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The target property to animate.
+ /// The callback to use to construct the custom animation.
+ /// The optional initial delay for the animation.
+ /// The repeat option for the animation (defaults to one iteration).
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder TimedKeyFrames(
+ string property,
+ Action> build,
+ TimeSpan? delay = null,
+ RepeatOption? repeat = null,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ where T : unmanaged
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ TimedKeyFrameAnimationBuilder.Composition builder = new(property, delay, repeat ?? RepeatOption.Once);
+
+ build(builder);
+
+ this.compositionAnimationFactories.Add(builder);
+ }
+ else
+ {
+ TimedKeyFrameAnimationBuilder.Xaml builder = new(property, delay, repeat ?? RepeatOption.Once);
+
+ build(builder);
+
+ this.xamlAnimationFactories.Add(builder);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a custom animation based on timed keyframes to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The type of state to pass to the builder.
+ /// The target property to animate.
+ /// The state to pass to the builder.
+ /// The callback to use to construct the custom animation.
+ /// The optional initial delay for the animation.
+ /// The repeat option for the animation (defaults to one iteration).
+ /// The target framework layer to animate.
+ /// The current instance.
+ public AnimationBuilder TimedKeyFrames(
+ string property,
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay = null,
+ RepeatOption? repeatOption = null,
+ FrameworkLayer layer = FrameworkLayer.Composition)
+ where T : unmanaged
+ {
+ if (layer == FrameworkLayer.Composition)
+ {
+ TimedKeyFrameAnimationBuilder.Composition builder = new(property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ this.compositionAnimationFactories.Add(builder);
+ }
+ else
+ {
+ TimedKeyFrameAnimationBuilder.Xaml builder = new(property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ this.xamlAnimationFactories.Add(builder);
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.PropertyBuilders.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.PropertyBuilders.cs
new file mode 100644
index 00000000000..9775b507c0e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.PropertyBuilders.cs
@@ -0,0 +1,270 @@
+// 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.
+
+using System;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
+
+#nullable enable
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// A custom for a shared animation.
+ ///
+ /// The type of property to animate.
+ private sealed record PropertyAnimationBuilder(
+ AnimationBuilder Builder,
+ string Property,
+ FrameworkLayer Layer)
+ : IPropertyAnimationBuilder
+ where T : unmanaged
+ {
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ return Builder.NormalizedKeyFrames(Property, build, delay, duration, repeatOption, Layer);
+ }
+
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ return Builder.NormalizedKeyFrames(Property, state, build, delay, duration, repeatOption, Layer);
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ return Builder.TimedKeyFrames(Property, build, delay, repeatOption, Layer);
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ return Builder.TimedKeyFrames(Property, state, build, delay, repeatOption, Layer);
+ }
+ }
+
+ ///
+ /// A custom for a composition clip animation.
+ ///
+ private sealed record CompositionClipAnimationBuilder(
+ AnimationBuilder Builder,
+ string Property)
+ : IPropertyAnimationBuilder
+ {
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ NormalizedKeyFrameAnimationBuilder.Composition builder = new(
+ Property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ Builder.compositionAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ NormalizedKeyFrameAnimationBuilder.Composition builder = new(
+ Property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ Builder.compositionAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ TimedKeyFrameAnimationBuilder.Composition builder = new(Property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ Builder.compositionAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ TimedKeyFrameAnimationBuilder.Composition builder = new(Property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ Builder.compositionAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ /// A private factory implementing .
+ ///
+ private sealed record Factory(ICompositionAnimationFactory Builder) : ICompositionAnimationFactory
+ {
+ ///
+ public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
+ {
+ Visual visual = (Visual)targetHint;
+ InsetClip clip = visual.Clip as InsetClip ?? (InsetClip)(visual.Clip = visual.Compositor.CreateInsetClip());
+ CompositionAnimation animation = Builder.GetAnimation(clip, out _);
+
+ target = clip;
+
+ return animation;
+ }
+ }
+ }
+
+ ///
+ /// A custom for a XAML transform animation.
+ ///
+ private sealed record XamlTransformPropertyAnimationBuilder(
+ AnimationBuilder Builder,
+ string Property)
+ : IPropertyAnimationBuilder
+ {
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ NormalizedKeyFrameAnimationBuilder.Xaml builder = new(
+ Property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ Builder.xamlAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder NormalizedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ RepeatOption? repeatOption)
+ {
+ NormalizedKeyFrameAnimationBuilder.Xaml builder = new(
+ Property,
+ delay,
+ duration ?? DefaultDuration,
+ repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ Builder.xamlAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ Action> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ TimedKeyFrameAnimationBuilder.Xaml builder = new(Property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder);
+
+ Builder.xamlAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ public AnimationBuilder TimedKeyFrames(
+ TState state,
+ Action, TState> build,
+ TimeSpan? delay,
+ RepeatOption? repeatOption)
+ {
+ TimedKeyFrameAnimationBuilder.Xaml builder = new(Property, delay, repeatOption ?? RepeatOption.Once);
+
+ build(builder, state);
+
+ Builder.xamlAnimationFactories.Add(new Factory(builder));
+
+ return Builder;
+ }
+
+ ///
+ /// A private factory implementing .
+ ///
+ private sealed record Factory(IXamlAnimationFactory Builder) : IXamlAnimationFactory
+ {
+ ///
+ public Timeline GetAnimation(DependencyObject targetHint)
+ {
+ UIElement element = (UIElement)targetHint;
+
+ if (element.RenderTransform is not CompositeTransform transform)
+ {
+ element.RenderTransform = transform = new CompositeTransform();
+ }
+
+ return Builder.GetAnimation(transform);
+ }
+ }
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Setup.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Setup.cs
new file mode 100644
index 00000000000..f095bab5736
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Setup.cs
@@ -0,0 +1,133 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Media.Animation;
+using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ /// A that allows to build custom animations targeting both the XAML and composition layers.
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// The list of instances representing factories for composition animations to run.
+ ///
+ private readonly List compositionAnimationFactories = new();
+
+ ///
+ /// The list of instances representing factories for XAML animations to run.
+ ///
+ private readonly List xamlAnimationFactories = new();
+
+ ///
+ /// Adds a new composition animation to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The target property to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The animation duration.
+ /// The easing function for the animation.
+ /// The easing mode for the animation.
+ /// The current instance.
+ private AnimationBuilder AddCompositionAnimationFactory(
+ string property,
+ T to,
+ T? from,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ EasingType easingType,
+ EasingMode easingMode)
+ where T : unmanaged
+ {
+ AnimationFactory animation = new(
+ property,
+ to,
+ from,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode);
+
+ this.compositionAnimationFactories.Add(animation);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new XAML animation to the current schedule.
+ ///
+ /// The type of values to animate.
+ /// The target property to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The animation duration.
+ /// The easing function for the animation.
+ /// The easing mode for the animation.
+ /// The current instance.
+ private AnimationBuilder AddXamlAnimationFactory(
+ string property,
+ T to,
+ T? from,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ EasingType easingType,
+ EasingMode easingMode)
+ where T : unmanaged
+ {
+ AnimationFactory animation = new(
+ property,
+ to,
+ from,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode);
+
+ this.xamlAnimationFactories.Add(animation);
+
+ return this;
+ }
+
+ ///
+ /// Adds a new XAML transform animation to the current schedule.
+ ///
+ /// The target property to animate.
+ /// The final value for the animation.
+ /// The optional starting value for the animation.
+ /// The optional initial delay for the animation.
+ /// The animation duration.
+ /// The easing function for the animation.
+ /// The easing mode for the animation.
+ /// The current instance.
+ private AnimationBuilder AddXamlTransformDoubleAnimationFactory(
+ string property,
+ double to,
+ double? from,
+ TimeSpan? delay,
+ TimeSpan? duration,
+ EasingType easingType,
+ EasingMode easingMode)
+ {
+ XamlTransformDoubleAnimationFactory animation = new(
+ property,
+ to,
+ from,
+ delay ?? DefaultDelay,
+ duration ?? DefaultDuration,
+ easingType,
+ easingMode);
+
+ this.xamlAnimationFactories.Add(animation);
+
+ return this;
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.cs
new file mode 100644
index 00000000000..c139e01a288
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.cs
@@ -0,0 +1,313 @@
+// 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.
+
+#nullable enable
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.UI.Composition;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Hosting;
+using Windows.UI.Xaml.Media.Animation;
+
+namespace Microsoft.Toolkit.Uwp.UI.Animations
+{
+ ///
+ /// A that allows to build custom animations targeting both the XAML and composition layers.
+ ///
+ public sealed partial class AnimationBuilder
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// This is private as the public entry point is the method.
+ private AnimationBuilder()
+ {
+ }
+
+ ///
+ ///
+ /// Creates a new instance to setup an animation schedule.
+ /// This can be used as the entry point to construct a custom animation sequence.
+ ///
+ /// For instance:
+ ///
+ /// AnimationBuilder.Create()
+ /// .Opacity(from: 0, to: 1)
+ /// .Translation(Axis.X, from: -40, to: 0)
+ /// .Start(MyButton);
+ ///
+ ///
+ /// Configured instances are also reusable, meaning that the same
+ /// one can be used to start an animation sequence on multiple elements as well.
+ ///
+ /// For instance:
+ ///
+ /// var animation = AnimationBuilder.Create().Opacity(0, 1).Size(1.2, 1);
+ ///
+ /// animation.Start(MyButton);
+ /// animation.Start(MyGrid);
+ ///
+ /// Alternatively, the type can be used to configure animations directly from XAML.
+ /// The same APIs will still be used behind the scenes to handle animations.
+ ///
+ /// An empty instance to use to construct an animation sequence.
+ [Pure]
+ public static AnimationBuilder Create() => new();
+
+ ///
+ /// Starts the animations present in the current instance.
+ ///
+ /// The target to animate.
+ public void Start(UIElement element)
+ {
+ if (this.compositionAnimationFactories.Count > 0)
+ {
+ ElementCompositionPreview.SetIsTranslationEnabled(element, true);
+
+ Visual visual = ElementCompositionPreview.GetElementVisual(element);
+
+ foreach (var factory in this.compositionAnimationFactories)
+ {
+ var animation = factory.GetAnimation(visual, out var target);
+
+ if (target is null)
+ {
+ visual.StartAnimation(animation.Target, animation);
+ }
+ else
+ {
+ target.StartAnimation(animation.Target, animation);
+ }
+ }
+ }
+
+ if (this.xamlAnimationFactories.Count > 0)
+ {
+ Storyboard storyboard = new();
+
+ foreach (var factory in this.xamlAnimationFactories)
+ {
+ storyboard.Children.Add(factory.GetAnimation(element));
+ }
+
+ storyboard.Begin();
+ }
+ }
+
+ ///
+ /// Starts the animations present in the current instance, and
+ /// registers a given cancellation token to stop running animations before they complete.
+ ///
+ /// The target to animate.
+ /// The cancellation token to stop animations while they're running.
+ public void Start(UIElement element, CancellationToken token)
+ {
+ List<(CompositionObject Target, string Path)>? compositionAnimations = null;
+
+ if (this.compositionAnimationFactories.Count > 0)
+ {
+ compositionAnimations = new List<(CompositionObject Target, string Path)>(this.compositionAnimationFactories.Count);
+
+ ElementCompositionPreview.SetIsTranslationEnabled(element, true);
+
+ Visual visual = ElementCompositionPreview.GetElementVisual(element);
+
+ foreach (var factory in this.compositionAnimationFactories)
+ {
+ var animation = factory.GetAnimation(visual, out var target);
+
+ if (target is null)
+ {
+ visual.StartAnimation(animation.Target, animation);
+ }
+ else
+ {
+ target.StartAnimation(animation.Target, animation);
+ }
+
+ compositionAnimations.Add((target ?? visual, animation.Target));
+ }
+ }
+
+ Storyboard? storyboard = null;
+
+ if (this.xamlAnimationFactories.Count > 0)
+ {
+ storyboard = new Storyboard();
+
+ foreach (var factory in this.xamlAnimationFactories)
+ {
+ storyboard.Children.Add(factory.GetAnimation(element));
+ }
+
+ storyboard.Begin();
+ }
+
+ static void Stop(object state)
+ {
+ (List<(CompositionObject Target, string Path)>? animations, Storyboard? storyboard) = ((List<(CompositionObject, string)>?, Storyboard?))state;
+
+ if (animations is not null)
+ {
+ foreach (var (target, path) in animations)
+ {
+ target.StopAnimation(path);
+ }
+ }
+
+ storyboard?.Stop();
+ }
+
+ token.Register(static obj => Stop(obj), (compositionAnimations, storyboard));
+ }
+
+ ///
+ /// Starts the animations present in the current instance.
+ ///
+ /// The target to animate.
+ /// A that completes when all animations have completed.
+ public Task StartAsync(UIElement element)
+ {
+ Task
+ compositionTask = Task.CompletedTask,
+ xamlTask = Task.CompletedTask;
+
+ if (this.compositionAnimationFactories.Count > 0)
+ {
+ ElementCompositionPreview.SetIsTranslationEnabled(element, true);
+
+ Visual visual = ElementCompositionPreview.GetElementVisual(element);
+ CompositionScopedBatch batch = visual.Compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
+ TaskCompletionSource