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
Original file line number Diff line number Diff line change
Expand Up @@ -108,25 +108,35 @@ protected override void OnDetaching()

private static void OnValueChanged(AvaloniaPropertyChangedEventArgs args)
{
if (args.Sender is not BindingTriggerBehavior behavior || behavior.AssociatedObject is null)
if (args.Sender is not BindingTriggerBehavior behavior)
{
return;
}

if (!behavior.IsEnabled)
behavior.Execute(parameter: args);
}

private void Execute(object? parameter)
{
if (AssociatedObject is null)
{
return;
}

if (!IsEnabled)
{
return;
}

// NOTE: In UWP version binding null check is not present but Avalonia throws exception as Bindings are null when first initialized.
var binding = behavior.BindingValue;
var binding = BindingValue;
if (binding is not null)
{
// Some value has changed--either the binding value, reference value, or the comparison condition. Re-evaluate the equation.
if (ComparisonConditionTypeHelper.Compare(behavior.BindingValue, behavior.ComparisonCondition,
behavior.Value))
if (ComparisonConditionTypeHelper.Compare(BindingValue, ComparisonCondition,
Value))
{
Interaction.ExecuteActions(behavior.AssociatedObject, behavior.Actions, args);
Interaction.ExecuteActions(AssociatedObject, Actions, parameter);
}
}
}
Expand Down
23 changes: 17 additions & 6 deletions src/Avalonia.Xaml.Interactions/Core/DataTriggerBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Reactive;
using Avalonia.Xaml.Interactivity;

Expand Down Expand Up @@ -69,24 +70,34 @@ static DataTriggerBehavior()

private static void OnValueChanged(AvaloniaPropertyChangedEventArgs args)
{
if (args.Sender is not DataTriggerBehavior behavior || behavior.AssociatedObject is null)
if (args.Sender is not DataTriggerBehavior behavior)
{
return;
}

if (!behavior.IsEnabled)
behavior.Execute(parameter: args);
}

private void Execute(object? parameter)
{
if (AssociatedObject is null)
{
return;
}

if (!IsEnabled)
{
return;
}

// NOTE: In UWP version binding null check is not present but Avalonia throws exception as Bindings are null when first initialized.
var binding = behavior.Binding;
var binding = Binding;
if (binding is not null)
{
// Some value has changed--either the binding value, reference value, or the comparison condition. Re-evaluate the equation.
if (ComparisonConditionTypeHelper.Compare(behavior.Binding, behavior.ComparisonCondition, behavior.Value))
if (ComparisonConditionTypeHelper.Compare(Binding, ComparisonCondition, Value))
{
Interaction.ExecuteActions(behavior.AssociatedObject, behavior.Actions, args);
Interaction.ExecuteActions(AssociatedObject, Actions, parameter);
}
}
}
Expand Down
56 changes: 52 additions & 4 deletions src/Avalonia.Xaml.Interactivity/Behavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@ protected virtual void OnDetaching()

void IBehaviorEventsHandler.UnloadedEventHandler() => OnUnloaded();

void IBehaviorEventsHandler.InitializedEventHandler() => OnInitializedEvent();

void IBehaviorEventsHandler.DataContextChangedEventHandler() => OnDataContextChangedEvent();

void IBehaviorEventsHandler.ResourcesChangedEventHandler() => OnResourcesChangedEvent();

void IBehaviorEventsHandler.ActualThemeVariantChangedEventHandler() => OnActualThemeVariantChangedEvent();

/// <summary>
/// Called after the <see cref="AssociatedObject"/> is attached to the visual tree.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Control"/>.
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Visual"/>.
/// </remarks>
protected virtual void OnAttachedToVisualTree()
{
Expand All @@ -111,7 +119,7 @@ protected virtual void OnAttachedToVisualTree()
/// Called when the <see cref="AssociatedObject"/> is being detached from the visual tree.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Control"/>.
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Visual"/>.
/// </remarks>
protected virtual void OnDetachedFromVisualTree()
{
Expand All @@ -121,7 +129,7 @@ protected virtual void OnDetachedFromVisualTree()
/// Called after the <see cref="AssociatedObject"/> is attached to the logical tree.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Control"/>.
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnAttachedToLogicalTree()
{
Expand All @@ -131,7 +139,7 @@ protected virtual void OnAttachedToLogicalTree()
/// Called when the <see cref="AssociatedObject"/> is being detached from the logical tree.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="Control"/>.
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnDetachedFromLogicalTree()
{
Expand All @@ -156,4 +164,44 @@ protected virtual void OnLoaded()
protected virtual void OnUnloaded()
{
}

/// <summary>
/// Called when the <see cref="AssociatedObject"/> is initialized.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnInitializedEvent()
{
}

/// <summary>
/// Called when the <see cref="AssociatedObject"/> DataContext changed.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnDataContextChangedEvent()
{
}

/// <summary>
/// Called when the <see cref="AssociatedObject"/> Resources changed.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnResourcesChangedEvent()
{
}

/// <summary>
/// Called when the <see cref="AssociatedObject"/> ActualThemeVariant changed.
/// </summary>
/// <remarks>
/// Invoked only when the <see cref="AssociatedObject"/> is of type <see cref="StyledElement"/>.
/// </remarks>
protected virtual void OnActualThemeVariantChangedEvent()
{
}
}
44 changes: 44 additions & 0 deletions src/Avalonia.Xaml.Interactivity/BehaviorCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,50 @@ internal void Unloaded()
}
}

internal void Initialized()
{
foreach (var item in this)
{
if (item is IBehaviorEventsHandler behaviorEventsHandler and IBehavior { AssociatedObject: not null })
{
behaviorEventsHandler.InitializedEventHandler();
}
}
}

internal void DataContextChanged()
{
foreach (var item in this)
{
if (item is IBehaviorEventsHandler behaviorEventsHandler and IBehavior { AssociatedObject: not null })
{
behaviorEventsHandler.DataContextChangedEventHandler();
}
}
}

internal void ResourcesChanged()
{
foreach (var item in this)
{
if (item is IBehaviorEventsHandler behaviorEventsHandler and IBehavior { AssociatedObject: not null })
{
behaviorEventsHandler.ResourcesChangedEventHandler();
}
}
}

internal void ActualThemeVariantChanged()
{
foreach (var item in this)
{
if (item is IBehaviorEventsHandler behaviorEventsHandler and IBehavior { AssociatedObject: not null })
{
behaviorEventsHandler.ActualThemeVariantChangedEventHandler();
}
}
}

private void BehaviorCollection_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs eventArgs)
{
if (eventArgs.Action == NotifyCollectionChangedAction.Reset)
Expand Down
20 changes: 20 additions & 0 deletions src/Avalonia.Xaml.Interactivity/IBehaviorEventsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,24 @@ public interface IBehaviorEventsHandler
/// Called when element is unloaded.
/// </summary>
void UnloadedEventHandler();

/// <summary>
/// Called when element is initialized.
/// </summary>
void InitializedEventHandler();

/// <summary>
/// Called when element DataContext changed.
/// </summary>
void DataContextChangedEventHandler();

/// <summary>
/// Called when element Resources changed.
/// </summary>
void ResourcesChangedEventHandler();

/// <summary>
/// Called when element ActualThemeVariant changed.
/// </summary>
void ActualThemeVariantChangedEventHandler();
}
Loading
Loading