feat: polish popup open.

This commit is contained in:
Dong Bin
2025-04-18 12:44:55 +08:00
parent 5da5e0626a
commit 713c1731c9
2 changed files with 52 additions and 9 deletions

View File

@@ -6,8 +6,10 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="u:PopConfirm"> <ControlTemplate TargetType="u:PopConfirm">
<Panel> <Panel>
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/> <ContentPresenter Name="PART_ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
<Popup IsOpen="True" <Popup
IsLightDismissEnabled="True"
OverlayInputPassThroughElement="{Binding #PART_ContentPresenter}"
Name="{x:Static u:PopConfirm.PART_Popup}" Name="{x:Static u:PopConfirm.PART_Popup}"
Placement="Bottom" > Placement="Bottom" >
<Border Theme="{DynamicResource CardBorder}"> <Border Theme="{DynamicResource CardBorder}">

View File

@@ -1,4 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Input; using System.Windows.Input;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
@@ -103,6 +104,15 @@ public class PopConfirm: ContentControl
set => SetValue(TriggerModeProperty, value); set => SetValue(TriggerModeProperty, value);
} }
public static readonly StyledProperty<bool> HandleAsyncCommandProperty = AvaloniaProperty.Register<PopConfirm, bool>(
nameof(HandleAsyncCommand), true);
public bool HandleAsyncCommand
{
get => GetValue(HandleAsyncCommandProperty);
set => SetValue(HandleAsyncCommandProperty, value);
}
static PopConfirm() static PopConfirm()
{ {
ConfirmCommandProperty.Changed.AddClassHandler<PopConfirm, ICommand?>((popconfirm, args) => popconfirm.OnCommandChanged(args)); ConfirmCommandProperty.Changed.AddClassHandler<PopConfirm, ICommand?>((popconfirm, args) => popconfirm.OnCommandChanged(args));
@@ -140,20 +150,44 @@ public class PopConfirm: ContentControl
private void OnButtonClicked(object sender, RoutedEventArgs e) private void OnButtonClicked(object sender, RoutedEventArgs e)
{ {
// This is a hack for MVVM toolkit that uses INotifyPropertyChanged for async command. It counts the number of if (!HandleAsyncCommand)
{
_popup?.SetValue(Popup.IsOpenProperty, false);
}
// This is a hack for MVVM toolkit and Prism that uses INotifyPropertyChanged for async command. It counts the number of
// IsRunning property changes to determine when the command is finished. // IsRunning property changes to determine when the command is finished.
if (sender is Button button && button.Command is INotifyPropertyChanged inpc) if (sender is Button button && button.Command is { } command and INotifyPropertyChanged)
{ {
var count = 0; var count = 0;
void OnCommandPropertyChanged(object? sender, PropertyChangedEventArgs args) void OnCanExecuteChanged(object? _, System.EventArgs e)
{ {
if (args.PropertyName != "IsRunning") return;
count++; count++;
if (count != 2) return; if (count != 2) return;
inpc.PropertyChanged -= OnCommandPropertyChanged; var canExecute = command.CanExecute(button.CommandParameter);
_popup?.SetValue(Popup.IsOpenProperty, false); if (canExecute == true)
{
command.CanExecuteChanged -= OnCanExecuteChanged;
_popup?.SetValue(Popup.IsOpenProperty, false);
}
} }
inpc.PropertyChanged += OnCommandPropertyChanged; command.CanExecuteChanged += OnCanExecuteChanged;
}
// TODO: This is a hack for ReactiveUI that ReactiveCommand is an IDisposable.
else if (sender is Button b2 && b2.Command is { } command2 and IDisposable)
{
var count = 0;
void OnCanExecuteChanged2(object? _, System.EventArgs e)
{
count++;
if (count != 2) return;
var canExecute = command2.CanExecute(b2.CommandParameter);
if (canExecute == true)
{
command2.CanExecuteChanged -= OnCanExecuteChanged2;
_popup?.SetValue(Popup.IsOpenProperty, false);
}
}
command2.CanExecuteChanged += OnCanExecuteChanged2;
} }
else else
{ {
@@ -175,6 +209,13 @@ public class PopConfirm: ContentControl
private void OnChildChanged(AvaloniaPropertyChangedEventArgs arg) private void OnChildChanged(AvaloniaPropertyChangedEventArgs arg)
{ {
if (arg.GetNewValue<Control?>() is null) return; if (arg.GetNewValue<Control?>() is null) return;
if (arg.GetNewValue<Control?>() is Button button)
{
button.Click+= (o, e) =>
{
_popup?.SetValue(Popup.IsOpenProperty, !_popup.IsOpen);
};
}
} }
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)