AvaloniaUI / Avalonia.Xaml.Behaviors

Port of Windows UWP Xaml Behaviors for Avalonia Xaml.
MIT License
385 stars 46 forks source link

DataTriggerBehavior does not work correctly in ContextMenu #137

Closed Zaspard closed 6 months ago

Zaspard commented 1 year ago

DataTriggerBehavior does not work correctly in ContextMenu (maybe in other deleted elements from the visual tree like Popup). The value from the model is correctly read only the first time the ContextMenu is opened, the second time the ContextMenu does not know about the update because the Behavior.Detach() method was called.

Videos:

https://github.com/AvaloniaUI/Avalonia.Xaml.Behaviors/assets/45457436/76e18c1b-81e2-43fd-b3cd-08fbdf3a10e2

https://github.com/AvaloniaUI/Avalonia.Xaml.Behaviors/assets/45457436/fa0c71a2-0077-4a29-907f-f99eeb1d30e6

Example: BehaviorsTestApplication.zip

I tried fixing this by adding an override to the DataTriggerBehavior.OnAttached() method, but I'm not sure if this is correct.

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

    TryExecuteActions(behavior.AssociatedObject,
                      behavior.Binding,
                      behavior.ComparisonCondition,
                      behavior.Value,
                      behavior.Actions);
}

/// <summary>
/// Called after the behavior is attached to the <see cref="Behavior.AssociatedObject"/>.
/// </summary>
protected override void OnAttached()
{
    base.OnAttached();

    if (AssociatedObject is null)
    {
        return;
    }

    TryExecuteActions(AssociatedObject, Binding, ComparisonCondition, Value, Actions);
}

static void TryExecuteActions(AvaloniaObject? associatedObject,
                              object? binding,
                              ComparisonConditionType comparisonCondition,
                              object? value,
                              ActionCollection actions)
{
    // NOTE: In UWP version binding null check is not present but Avalonia throws exception as Bindings are null when first initialized.
    if (binding is { })
    {
        // Some value has changed--either the binding value, reference value, or the comparison condition. Re-evaluate the equation.
        if (Compare(binding, comparisonCondition, value))
        {
            Interaction.ExecuteActions(associatedObject, actions, null);
        }
    }
}

I can create a PR with this change if necessary. Result:

https://github.com/AvaloniaUI/Avalonia.Xaml.Behaviors/assets/45457436/db81c6cc-b0bc-4af5-809f-ae66b6c1b79e