Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AvaloniaBehaviors.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
<File Path="README.md" />
</Folder>
<Folder Name="/samples/">
<Project Path="samples/AnimationsTestApplication/AnimationsTestApplication.csproj" />
<Project Path="samples/BehaviorsTestApplication/BehaviorsTestApplication.csproj" />
<Project Path="samples/SourceGeneratorSample/SourceGeneratorSample.csproj" />
</Folder>
<Folder Name="/src/">
<Project Path="src/Xaml.Behaviors.Animations/Xaml.Behaviors.Animations.csproj" />
<Project Path="src/Xaml.Behaviors.Avalonia/Xaml.Behaviors.Avalonia.csproj" />
<Project Path="src/Xaml.Behaviors.Interactions.Custom/Xaml.Behaviors.Interactions.Custom.csproj" />
<Project Path="src/Xaml.Behaviors.Interactions.DragAndDrop.DataGrid/Xaml.Behaviors.Interactions.DragAndDrop.DataGrid.csproj" />
Expand All @@ -47,6 +49,7 @@
<Project Path="src/Xaml.Behaviors/Xaml.Behaviors.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/Xaml.Behaviors.Animations.UnitTests/Xaml.Behaviors.Animations.UnitTests.csproj" />
<Project Path="tests/Xaml.Behaviors.Interactions.UnitTests/Xaml.Behaviors.Interactions.UnitTests.csproj" />
<Project Path="tests/Xaml.Behaviors.Interactivity.UnitTests/Xaml.Behaviors.Interactivity.UnitTests.csproj" />
<Project Path="tests/Xaml.Behaviors.SourceGenerators.IntegrationTests/Xaml.Behaviors.SourceGenerators.IntegrationTests.csproj" />
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ In addition to the classic reflection-based behaviors from WPF/UWP, this port ad

See the [AOT-friendly behaviors docs](docfx/articles/source-generators/index.md) for examples and guidance.

Animation definitions and composition helpers are also available independently through `Xaml.Behaviors.Animations`. This package depends on Avalonia only; behavior, action, and trigger adapters in `Xaml.Behaviors.Interactions.Custom` reuse the same implementation. See the [standalone animations guide](docfx/articles/animations/index.md).

The [standalone animations sample](samples/AnimationsTestApplication/README.md) demonstrates every feature family in a dedicated tab without referencing the behaviors framework.

## Building XAML Behaviors Avalonia

First, clone the repository or download the latest zip.
Expand Down Expand Up @@ -75,6 +79,7 @@ and install the package like this:
| Package | NuGet | Description |
|---------|-------|-------------|
| [Xaml.Behaviors](https://www.nuget.org/packages/Xaml.Behaviors) | [![NuGet](https://img.shields.io/nuget/v/Xaml.Behaviors.svg)](https://www.nuget.org/packages/Xaml.Behaviors) | Complete library of behaviors, actions and triggers for Avalonia applications. |
| [Xaml.Behaviors.Animations](https://www.nuget.org/packages/Xaml.Behaviors.Animations) | [![NuGet](https://img.shields.io/nuget/v/Xaml.Behaviors.Animations.svg)](https://www.nuget.org/packages/Xaml.Behaviors.Animations) | Reusable Avalonia animations, composition effects, and transition helpers with no behaviors dependency. |
| [Xaml.Behaviors.Avalonia](https://www.nuget.org/packages/Xaml.Behaviors.Avalonia) | [![NuGet](https://img.shields.io/nuget/v/Xaml.Behaviors.Avalonia.svg)](https://www.nuget.org/packages/Xaml.Behaviors.Avalonia) | Meta package that bundles all Avalonia XAML Behaviors for easy installation. |
| [Xaml.Behaviors.Interactivity](https://www.nuget.org/packages/Xaml.Behaviors.Interactivity) | [![NuGet](https://img.shields.io/nuget/v/Xaml.Behaviors.Interactivity.svg)](https://www.nuget.org/packages/Xaml.Behaviors.Interactivity) | Foundation library providing base classes for actions, triggers and behaviors. |
| [Xaml.Behaviors.Interactions](https://www.nuget.org/packages/Xaml.Behaviors.Interactions) | [![NuGet](https://img.shields.io/nuget/v/Xaml.Behaviors.Interactions.svg)](https://www.nuget.org/packages/Xaml.Behaviors.Interactions) | Core collection of common triggers and actions for Avalonia. |
Expand Down
91 changes: 91 additions & 0 deletions docfx/articles/animations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Standalone animations

`Xaml.Behaviors.Animations` is the reusable animation layer for this repository. It targets `net8.0` and `net10.0`, depends only on Avalonia, and does not reference `Xaml.Behaviors.Interactivity` or any interactions package.

Install it when an application or library needs the animation implementations without behavior, action, or trigger types:

```xml
<PackageReference Include="Xaml.Behaviors.Animations" Version="..." />
```

The repository includes an [animations-only sample application](https://github.com/wieslawsoltes/Xaml.Behaviors/tree/master/samples/AnimationsTestApplication) with a dedicated tab for every feature family. Its project references only Avalonia and `Xaml.Behaviors.Animations`.

## API groups

| Group | APIs |
| --- | --- |
| Avalonia key-frame animation | `AnimationFactory`, `AnimationRunner`, `FluidMoveAnimation`, `IAnimationBuilder` |
| Composition catalogs | `AttentionAnimations`, `EntranceAnimations`, `ExitAnimations`, `FramerMotionAnimations`, `SpecialAnimations` |
| Composition primitives | `FadeAnimation`, `RotateAnimation`, `ScaleAnimation`, `SlidingAnimation` |
| Reusable effects | `OrbitAnimation`, `ParallaxAnimation`, `TiltAnimation` |
| Selection animation | `SelectionIndicatorAnimation`, `SelectingItemsControlBehavior` attached property |
| Transitions | `TransitionOperations` |

The CLR namespace remains `Avalonia.Xaml.Interactions.Custom` for source and XAML compatibility with earlier releases. The types now live in the `Xaml.Behaviors.Animations` assembly, while `Xaml.Behaviors.Interactions.Custom` ships type forwarders for legacy assembly-qualified references.

## XAML composition animations

The composition catalogs are attached properties, so they can be used with no behavior collection:

```xml
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:Avalonia.Xaml.Interactions.Custom">
<Border
Width="220"
Height="150"
animations:EntranceAnimations.FadeInUp="800" />
</UserControl>
```

The attached values are durations in milliseconds. The animation begins when the element receives a composition visual. A zero duration applies the final key-frame state immediately; a positive duration runs through the compositor.

## Direct use from code

Create and run a normal Avalonia animation. Async variants return the completion task when callers need to coordinate follow-up work:

```csharp
using Avalonia.Controls;
using Avalonia.Xaml.Interactions.Custom;

public static class WelcomeAnimation
{
public static void Start(Control target)
{
var animation = AnimationFactory.CreateFadeIn(
TimeSpan.FromMilliseconds(150),
TimeSpan.FromMilliseconds(350));

AnimationRunner.TryRun(animation, target);
}
}
```

`AnimationRunner.TryBuildAndRunAsync` applies the same explicit-animation-first selection used by the behavior adapters and returns `null` when neither an animation nor a builder result is available. `FluidMoveAnimation.TryRun` prepares a control's translation transform before starting its movement animation.

Composition effects expose calculation and application separately where useful. For example, a scroll observer can retain a session from `ParallaxAnimation.TryCreate(target)` and call its `Apply(offset, ratio)` method without attaching `ParallaxBehavior`. The session preserves the target composition visual across scroll updates and adds each parallax delta to the target's layout offset. `OrbitAnimation` maintains its orientation state for callers, while `TiltAnimation` calculates an orientation directly from the target size and pointer position.

`SelectionIndicatorAnimation.TryStart` can animate explicitly supplied indicator/container visuals or resolve the conventional `PART_SelectedPipe` from two templated item containers. `SelectingItemsControlBehavior.EnableSelectionAnimation` is the convenient attached-property adapter over the same primitive.

Transition collection operations are likewise independent:

```csharp
var transition = new DoubleTransition
{
Property = Visual.OpacityProperty,
Duration = TimeSpan.FromMilliseconds(200)
};

TransitionOperations.Add(target, transition);

using IDisposable subscription = TransitionOperations.Observe(
target,
transitions => OnTransitionsReplaced(transitions));
```

`Observe` reports the current collection immediately and subsequent replacements until the returned subscription is disposed.

## Behavior adapters

Install `Xaml.Behaviors.Interactions.Custom` when XAML attachment lifecycle, triggers, or actions are desired. Its animation and transition adapters reference `Xaml.Behaviors.Animations` and use the same shared implementation; existing behavior XAML remains unchanged.
2 changes: 2 additions & 0 deletions docfx/articles/animations/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- name: Standalone Animations
href: index.md
6 changes: 6 additions & 0 deletions docfx/articles/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Understanding the internal architecture of `Xaml.Behaviors` helps in writing custom behaviors and debugging complex interactions. The library is built upon the concept of **Attached Properties** and a specific lifecycle management system.

## Package boundaries

`Xaml.Behaviors.Animations` contains reusable Avalonia key-frame animations, composition animation catalogs and effects, animation runners/builders, and transition operations. It references Avalonia only and can be installed without the Interactivity or Interactions packages.

`Xaml.Behaviors.Interactions.Custom` references that package and adds lifecycle adapters such as `FadeInBehavior`, `OrbitEffectBehavior`, actions, and triggers. This keeps animation mechanics independent from behavior attachment and action execution while preserving the existing public XAML APIs.

## Core Components

### 1. The `Interaction` Class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# IAnimationBuilder

The `IAnimationBuilder` interface allows for dynamic animation creation.
The `IAnimationBuilder` interface allows for dynamic animation creation. It is shipped by `Xaml.Behaviors.Animations` and has no behaviors dependency; the animation behaviors and actions consume the same interface.

```csharp
public interface IAnimationBuilder
Expand Down
6 changes: 5 additions & 1 deletion docfx/articles/interactions-custom/animations/overview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Animations

The `Animations` category contains the following interactions:
The `Animations` category contains behavior, action, and trigger adapters from `Xaml.Behaviors.Interactions.Custom`. They delegate animation creation and execution to the standalone `Xaml.Behaviors.Animations` package.

Applications that do not need behavior lifecycle adapters can use `AnimationFactory`, `AnimationRunner`, and `IAnimationBuilder` directly by referencing only `Xaml.Behaviors.Animations`. See the [standalone animations guide](../../animations/index.md).

The category contains the following interactions:

* [AnimateOnAttachedBehavior](animate-on-attached-behavior.md)
* [AnimationCompletedTrigger](animation-completed-trigger.md)
Expand Down
4 changes: 3 additions & 1 deletion docfx/articles/interactions-custom/composition/overview.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Composition

The `Composition` category contains the following interactions:
Composition animation catalogs and reusable effects are shipped by `Xaml.Behaviors.Animations`. The package can be used directly without Interactivity. `OrbitEffectBehavior`, `ParallaxBehavior`, and `TiltEffectBehavior` remain in `Xaml.Behaviors.Interactions.Custom` as pointer and lifecycle adapters over the reusable animation APIs.

See the [standalone animations guide](../../animations/index.md) for installation, the API inventory, and direct-use examples.
2 changes: 1 addition & 1 deletion docfx/articles/interactions-custom/transitions/overview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Transitions

The `Avalonia.Xaml.Interactions.Custom` package provides behaviors, actions and triggers for working with `Transitions` in Avalonia.
The `Avalonia.Xaml.Interactions.Custom` package provides behaviors, actions and triggers for working with `Transitions` in Avalonia. These adapters delegate collection changes to `TransitionOperations` from the standalone `Xaml.Behaviors.Animations` package.

## Actions

Expand Down
2 changes: 2 additions & 0 deletions docfx/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
href: architecture.md
- name: MVVM and Behaviors
href: mvvm-and-behaviors.md
- name: Animations
href: animations/toc.yml
- name: Interactivity
href: interactivity/toc.yml
- name: Interactions
Expand Down
1 change: 1 addition & 0 deletions docfx/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"src": [
{
"files": [
"src/Xaml.Behaviors.Animations/Xaml.Behaviors.Animations.csproj",
"src/Xaml.Behaviors.Interactions/Xaml.Behaviors.Interactions.csproj",
"src/Xaml.Behaviors.Interactions.Custom/Xaml.Behaviors.Interactions.Custom.csproj",
"src/Xaml.Behaviors.Interactions.DragAndDrop/Xaml.Behaviors.Interactions.DragAndDrop.csproj",
Expand Down
22 changes: 22 additions & 0 deletions samples/AnimationsTestApplication/AnimationsTestApplication.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>False</IsPackable>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.Desktop" />
<PackageReference Include="Avalonia.Fonts.Inter" />
<PackageReference Include="Avalonia.Themes.Fluent" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Xaml.Behaviors.Animations\Xaml.Behaviors.Animations.csproj" />
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions samples/AnimationsTestApplication/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AnimationsTestApplication.App"
Name="AnimationsTestApplication"
RequestedThemeVariant="Light">
<Application.Styles>
<FluentTheme />
<StyleInclude Source="/SideBar.axaml" />
<Style Selector="Button">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</Application.Styles>
</Application>
31 changes: 31 additions & 0 deletions samples/AnimationsTestApplication/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

using AnimationsTestApplication.Views;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

namespace AnimationsTestApplication;

public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
{
desktopLifetime.MainWindow = new MainWindow();
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
{
singleViewLifetime.MainView = new MainView();
}

base.OnFrameworkInitializationCompleted();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Xaml.Interactions.Custom;

namespace AnimationsTestApplication.Controls;

/// <summary>
/// Demonstrates direct fluid translation animations.
/// </summary>
public class FluidMoveAnimationDemoControl : ContentControl
{
private bool _reverse;

public static readonly StyledProperty<TimeSpan> DurationProperty =
AvaloniaProperty.Register<FluidMoveAnimationDemoControl, TimeSpan>(
nameof(Duration),
TimeSpan.FromMilliseconds(450));

public static readonly StyledProperty<double> DistanceProperty =
AvaloniaProperty.Register<FluidMoveAnimationDemoControl, double>(nameof(Distance), 180d);

public TimeSpan Duration
{
get => GetValue(DurationProperty);
set => SetValue(DurationProperty, value);
}

public double Distance
{
get => GetValue(DistanceProperty);
set => SetValue(DistanceProperty, value);
}

protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);

double offset = _reverse ? -Distance : Distance;
_reverse = !_reverse;
FluidMoveAnimation.TryRun(this, offset, 0d, Duration);
e.Handled = true;
}
}
Loading
Loading