feat: implement most feature.
This commit is contained in:
@@ -10,9 +10,8 @@
|
|||||||
x:Class="Ursa.Demo.Pages.PopConfirmDemo">
|
x:Class="Ursa.Demo.Pages.PopConfirmDemo">
|
||||||
<StackPanel HorizontalAlignment="Left">
|
<StackPanel HorizontalAlignment="Left">
|
||||||
<u:PopConfirm PopupHeader="Header" PopupContent="Content"
|
<u:PopConfirm PopupHeader="Header" PopupContent="Content"
|
||||||
ConfirmCommand="{Binding Path=ConfirmCommand}"
|
ConfirmCommand="{Binding ConfirmCommand}"
|
||||||
CancelCommand="{Binding Path=CancelCommand}"
|
CancelCommand="{Binding Path=CancelCommand}" >
|
||||||
>
|
|
||||||
<Button Content="Hello World"></Button>
|
<Button Content="Hello World"></Button>
|
||||||
</u:PopConfirm>
|
</u:PopConfirm>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -6,27 +6,38 @@
|
|||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:PopConfirm">
|
<ControlTemplate TargetType="u:PopConfirm">
|
||||||
<Panel>
|
<Panel>
|
||||||
<ContentPresenter Name="PART_ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
|
<ContentPresenter
|
||||||
|
Name="PART_ContentPresenter"
|
||||||
|
Content="{TemplateBinding Content}"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||||
<Popup
|
<Popup
|
||||||
IsLightDismissEnabled="True"
|
IsLightDismissEnabled="True"
|
||||||
|
IsOpen="{TemplateBinding IsDropdownOpen, Mode=TwoWay}"
|
||||||
OverlayInputPassThroughElement="{Binding #PART_ContentPresenter}"
|
OverlayInputPassThroughElement="{Binding #PART_ContentPresenter}"
|
||||||
Name="{x:Static u:PopConfirm.PART_Popup}"
|
Name="{x:Static u:PopConfirm.PART_Popup}"
|
||||||
Placement="Bottom" >
|
Placement="{TemplateBinding Placement}" >
|
||||||
<Border Theme="{DynamicResource CardBorder}">
|
<Border Theme="{DynamicResource CardBorder}">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<ContentPresenter Content="{TemplateBinding PopupHeader}" ContentTemplate="{TemplateBinding PopupHeaderTemplate}"/>
|
<ContentPresenter
|
||||||
<ContentPresenter Content="{TemplateBinding PopupContent}" ContentTemplate="{TemplateBinding PopupContentTemplate}"/>
|
Content="{TemplateBinding PopupHeader}"
|
||||||
<StackPanel Orientation="Horizontal">
|
ContentTemplate="{TemplateBinding PopupHeaderTemplate}"/>
|
||||||
<Button
|
<ContentPresenter
|
||||||
Name="{x:Static u:PopConfirm.PART_ConfirmButton}"
|
Content="{TemplateBinding PopupContent}"
|
||||||
Content="Confirm"
|
ContentTemplate="{TemplateBinding PopupContentTemplate}"/>
|
||||||
Command="{TemplateBinding ConfirmCommand}"
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
CommandParameter="{TemplateBinding ConfirmCommandParameter}"/>
|
|
||||||
<Button
|
<Button
|
||||||
Name="{x:Static u:PopConfirm.PART_CancelButton}"
|
Name="{x:Static u:PopConfirm.PART_CancelButton}"
|
||||||
Content="Cancel"
|
Margin="0 0 8 0"
|
||||||
|
Content="{DynamicResource STRING_MENU_DIALOG_CANCEL}"
|
||||||
Command="{TemplateBinding CancelCommand}"
|
Command="{TemplateBinding CancelCommand}"
|
||||||
CommandParameter="{TemplateBinding CancelCommandParameter}"/>
|
CommandParameter="{TemplateBinding CancelCommandParameter}"/>
|
||||||
|
<Button
|
||||||
|
Name="{x:Static u:PopConfirm.PART_ConfirmButton}"
|
||||||
|
Theme="{DynamicResource SolidButton}"
|
||||||
|
Content="{DynamicResource STRING_MENU_DIALOG_OK}"
|
||||||
|
Command="{TemplateBinding ConfirmCommand}"
|
||||||
|
CommandParameter="{TemplateBinding ConfirmCommandParameter}"/>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -1,142 +1,163 @@
|
|||||||
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;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Presenters;
|
using Avalonia.Controls.Presenters;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Irihi.Avalonia.Shared.Helpers;
|
using Irihi.Avalonia.Shared.Helpers;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
public class PopConfirm: ContentControl
|
[PseudoClasses(PC_DropdownOpen)]
|
||||||
|
public class PopConfirm : ContentControl
|
||||||
{
|
{
|
||||||
public const string PART_ConfirmButton = "PART_ConfirmButton";
|
public const string PART_ConfirmButton = "PART_ConfirmButton";
|
||||||
public const string PART_CancelButton = "PART_CancelButton";
|
public const string PART_CancelButton = "PART_CancelButton";
|
||||||
public const string PART_Popup = "PART_Popup";
|
public const string PART_Popup = "PART_Popup";
|
||||||
|
public const string PC_DropdownOpen = ":dropdownopen";
|
||||||
private Button? _confirmButton;
|
|
||||||
private Button? _cancelButton;
|
|
||||||
private Popup? _popup;
|
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> PopupHeaderProperty = AvaloniaProperty.Register<PopConfirm, object?>(
|
public static readonly StyledProperty<object?> PopupHeaderProperty = AvaloniaProperty.Register<PopConfirm, object?>(
|
||||||
nameof(PopupHeader));
|
nameof(PopupHeader));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IDataTemplate?> PopupHeaderTemplateProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, IDataTemplate?>(
|
||||||
|
nameof(PopupHeaderTemplate));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object?> PopupContentProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, object?>(
|
||||||
|
nameof(PopupContent));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IDataTemplate?> PopupContentTemplateProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, IDataTemplate?>(
|
||||||
|
nameof(PopupContentTemplate));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<ICommand?> ConfirmCommandProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, ICommand?>(
|
||||||
|
nameof(ConfirmCommand));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<ICommand?> CancelCommandProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, ICommand?>(
|
||||||
|
nameof(CancelCommand));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object?> ConfirmCommandParameterProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, object?>(
|
||||||
|
nameof(ConfirmCommandParameter));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<object?> CancelCommandParameterProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, object?>(
|
||||||
|
nameof(CancelCommandParameter));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<PopConfirmTriggerMode> TriggerModeProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, PopConfirmTriggerMode>(
|
||||||
|
nameof(TriggerMode));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> HandleAsyncCommandProperty =
|
||||||
|
AvaloniaProperty.Register<PopConfirm, bool>(
|
||||||
|
nameof(HandleAsyncCommand), true);
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> IsDropdownOpenProperty = AvaloniaProperty.Register<PopConfirm, bool>(
|
||||||
|
nameof(IsDropdownOpen));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<PlacementMode> PlacementProperty =
|
||||||
|
Popup.PlacementProperty.AddOwner<PopConfirm>();
|
||||||
|
|
||||||
|
private Button? _cancelButton;
|
||||||
|
|
||||||
|
|
||||||
|
private IDisposable? _childChangeDisposable;
|
||||||
|
|
||||||
|
private Button? _confirmButton;
|
||||||
|
private Popup? _popup;
|
||||||
|
|
||||||
|
static PopConfirm()
|
||||||
|
{
|
||||||
|
IsDropdownOpenProperty.AffectsPseudoClass<PopConfirm>(PC_DropdownOpen);
|
||||||
|
TriggerModeProperty.Changed.AddClassHandler<PopConfirm, PopConfirmTriggerMode>((pop, args) =>
|
||||||
|
pop.OnTriggerModeChanged(args));
|
||||||
|
}
|
||||||
|
|
||||||
public object? PopupHeader
|
public object? PopupHeader
|
||||||
{
|
{
|
||||||
get => GetValue(PopupHeaderProperty);
|
get => GetValue(PopupHeaderProperty);
|
||||||
set => SetValue(PopupHeaderProperty, value);
|
set => SetValue(PopupHeaderProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<IDataTemplate?> PopupHeaderTemplateProperty = AvaloniaProperty.Register<PopConfirm, IDataTemplate?>(
|
|
||||||
nameof(PopupHeaderTemplate));
|
|
||||||
|
|
||||||
public IDataTemplate? PopupHeaderTemplate
|
public IDataTemplate? PopupHeaderTemplate
|
||||||
{
|
{
|
||||||
get => GetValue(PopupHeaderTemplateProperty);
|
get => GetValue(PopupHeaderTemplateProperty);
|
||||||
set => SetValue(PopupHeaderTemplateProperty, value);
|
set => SetValue(PopupHeaderTemplateProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> PopupContentProperty = AvaloniaProperty.Register<PopConfirm, object?>(
|
|
||||||
nameof(PopupContent));
|
|
||||||
|
|
||||||
public object? PopupContent
|
public object? PopupContent
|
||||||
{
|
{
|
||||||
get => GetValue(PopupContentProperty);
|
get => GetValue(PopupContentProperty);
|
||||||
set => SetValue(PopupContentProperty, value);
|
set => SetValue(PopupContentProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<IDataTemplate?> PopupContentTemplateProperty = AvaloniaProperty.Register<PopConfirm, IDataTemplate?>(
|
|
||||||
nameof(PopupContentTemplate));
|
|
||||||
|
|
||||||
public IDataTemplate? PopupContentTemplate
|
public IDataTemplate? PopupContentTemplate
|
||||||
{
|
{
|
||||||
get => GetValue(PopupContentTemplateProperty);
|
get => GetValue(PopupContentTemplateProperty);
|
||||||
set => SetValue(PopupContentTemplateProperty, value);
|
set => SetValue(PopupContentTemplateProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<ICommand?> ConfirmCommandProperty = AvaloniaProperty.Register<PopConfirm, ICommand?>(
|
|
||||||
nameof(ConfirmCommand));
|
|
||||||
|
|
||||||
public ICommand? ConfirmCommand
|
public ICommand? ConfirmCommand
|
||||||
{
|
{
|
||||||
get => GetValue(ConfirmCommandProperty);
|
get => GetValue(ConfirmCommandProperty);
|
||||||
set => SetValue(ConfirmCommandProperty, value);
|
set => SetValue(ConfirmCommandProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<ICommand?> CancelCommandProperty = AvaloniaProperty.Register<PopConfirm, ICommand?>(
|
|
||||||
nameof(CancelCommand));
|
|
||||||
|
|
||||||
public ICommand? CancelCommand
|
public ICommand? CancelCommand
|
||||||
{
|
{
|
||||||
get => GetValue(CancelCommandProperty);
|
get => GetValue(CancelCommandProperty);
|
||||||
set => SetValue(CancelCommandProperty, value);
|
set => SetValue(CancelCommandProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> ConfirmCommandParameterProperty = AvaloniaProperty.Register<PopConfirm, object?>(
|
|
||||||
nameof(ConfirmCommandParameter));
|
|
||||||
|
|
||||||
public object? ConfirmCommandParameter
|
public object? ConfirmCommandParameter
|
||||||
{
|
{
|
||||||
get => GetValue(ConfirmCommandParameterProperty);
|
get => GetValue(ConfirmCommandParameterProperty);
|
||||||
set => SetValue(ConfirmCommandParameterProperty, value);
|
set => SetValue(ConfirmCommandParameterProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<object?> CancelCommandParameterProperty = AvaloniaProperty.Register<PopConfirm, object?>(
|
|
||||||
nameof(CancelCommandParameter));
|
|
||||||
|
|
||||||
public object? CancelCommandParameter
|
public object? CancelCommandParameter
|
||||||
{
|
{
|
||||||
get => GetValue(CancelCommandParameterProperty);
|
get => GetValue(CancelCommandParameterProperty);
|
||||||
set => SetValue(CancelCommandParameterProperty, value);
|
set => SetValue(CancelCommandParameterProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<PopConfirmTriggerMode> TriggerModeProperty =
|
|
||||||
AvaloniaProperty.Register<PopConfirm, PopConfirmTriggerMode>(
|
|
||||||
nameof(TriggerMode));
|
|
||||||
|
|
||||||
public PopConfirmTriggerMode TriggerMode
|
public PopConfirmTriggerMode TriggerMode
|
||||||
{
|
{
|
||||||
get => GetValue(TriggerModeProperty);
|
get => GetValue(TriggerModeProperty);
|
||||||
set => SetValue(TriggerModeProperty, value);
|
set => SetValue(TriggerModeProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> HandleAsyncCommandProperty = AvaloniaProperty.Register<PopConfirm, bool>(
|
|
||||||
nameof(HandleAsyncCommand), true);
|
|
||||||
|
|
||||||
public bool HandleAsyncCommand
|
public bool HandleAsyncCommand
|
||||||
{
|
{
|
||||||
get => GetValue(HandleAsyncCommandProperty);
|
get => GetValue(HandleAsyncCommandProperty);
|
||||||
set => SetValue(HandleAsyncCommandProperty, value);
|
set => SetValue(HandleAsyncCommandProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PopConfirm()
|
public bool IsDropdownOpen
|
||||||
{
|
{
|
||||||
ConfirmCommandProperty.Changed.AddClassHandler<PopConfirm, ICommand?>((popconfirm, args) => popconfirm.OnCommandChanged(args));
|
get => GetValue(IsDropdownOpenProperty);
|
||||||
|
set => SetValue(IsDropdownOpenProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCommandChanged(AvaloniaPropertyChangedEventArgs<ICommand?> args)
|
public PlacementMode Placement
|
||||||
{
|
{
|
||||||
|
get => GetValue(PlacementProperty);
|
||||||
|
set => SetValue(PlacementProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PopConfirm()
|
private void OnTriggerModeChanged(AvaloniaPropertyChangedEventArgs<PopConfirmTriggerMode> args)
|
||||||
{
|
{
|
||||||
|
var child = Presenter?.Child;
|
||||||
}
|
TeardownChildrenEventSubscriptions(child, args.GetOldValue<PopConfirmTriggerMode>());
|
||||||
|
SetupChildrenEventSubscriptions(child, args.GetNewValue<PopConfirmTriggerMode>());
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
||||||
{
|
|
||||||
base.OnPropertyChanged(change);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnContentChanged()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
@@ -148,76 +169,102 @@ public class PopConfirm: ContentControl
|
|||||||
Button.ClickEvent.AddHandler(OnButtonClicked, _confirmButton, _cancelButton);
|
Button.ClickEvent.AddHandler(OnButtonClicked, _confirmButton, _cancelButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnButtonClicked(object sender, RoutedEventArgs e)
|
private async void OnButtonClicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!HandleAsyncCommand)
|
if (!HandleAsyncCommand) _popup?.SetValue(Popup.IsOpenProperty, false);
|
||||||
{
|
|
||||||
_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
|
// 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 { } command and INotifyPropertyChanged)
|
if (sender is Button button && button.Command is { } command and (INotifyPropertyChanged or IDisposable))
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
void OnCanExecuteChanged(object? _, System.EventArgs e)
|
void OnCanExecuteChanged(object? _, System.EventArgs e)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (count != 2) return;
|
if (count != 2) return;
|
||||||
var canExecute = command.CanExecute(button.CommandParameter);
|
var canExecute = command.CanExecute(button.CommandParameter);
|
||||||
if (canExecute == true)
|
if (canExecute)
|
||||||
{
|
{
|
||||||
command.CanExecuteChanged -= OnCanExecuteChanged;
|
command.CanExecuteChanged -= OnCanExecuteChanged;
|
||||||
_popup?.SetValue(Popup.IsOpenProperty, false);
|
_popup?.SetValue(Popup.IsOpenProperty, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
command.CanExecuteChanged += OnCanExecuteChanged;
|
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
|
||||||
{
|
{
|
||||||
_popup?.SetValue(Popup.IsOpenProperty, false);
|
_popup?.SetValue(Popup.IsOpenProperty, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private IDisposable? _childChangeDisposable;
|
|
||||||
|
|
||||||
protected override bool RegisterContentPresenter(ContentPresenter presenter)
|
protected override bool RegisterContentPresenter(ContentPresenter presenter)
|
||||||
{
|
{
|
||||||
var result = base.RegisterContentPresenter(presenter);
|
var result = base.RegisterContentPresenter(presenter);
|
||||||
_childChangeDisposable = presenter.GetPropertyChangedObservable(ContentPresenter.ChildProperty).Subscribe(OnChildChanged);
|
_childChangeDisposable = presenter.GetPropertyChangedObservable(ContentPresenter.ChildProperty)
|
||||||
|
.Subscribe(OnChildChanged);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnChildChanged(AvaloniaPropertyChangedEventArgs arg)
|
private void OnChildChanged(AvaloniaPropertyChangedEventArgs arg)
|
||||||
{
|
{
|
||||||
|
TeardownChildrenEventSubscriptions(arg.GetOldValue<Control?>(), TriggerMode);
|
||||||
|
SetupChildrenEventSubscriptions(arg.GetNewValue<Control?>(), TriggerMode);
|
||||||
if (arg.GetNewValue<Control?>() is null) return;
|
if (arg.GetNewValue<Control?>() is null) return;
|
||||||
if (arg.GetNewValue<Control?>() is Button button)
|
if (arg.GetNewValue<Control?>() is Button button)
|
||||||
|
button.Click += (o, e) => { SetCurrentValue(IsDropdownOpenProperty, true); };
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupChildrenEventSubscriptions(Control? child, PopConfirmTriggerMode mode)
|
||||||
|
{
|
||||||
|
if (child is null) return;
|
||||||
|
if (mode == PopConfirmTriggerMode.Tap)
|
||||||
{
|
{
|
||||||
button.Click+= (o, e) =>
|
if (child is Button button)
|
||||||
{
|
Button.ClickEvent.AddHandler(OnMainButtonClicked, button);
|
||||||
_popup?.SetValue(Popup.IsOpenProperty, !_popup.IsOpen);
|
else
|
||||||
};
|
PointerPressedEvent.AddHandler(OnMainElementPressed, child);
|
||||||
|
}
|
||||||
|
else if (mode == PopConfirmTriggerMode.Focus)
|
||||||
|
{
|
||||||
|
GotFocusEvent.AddHandler(OnMainElementGotFocus, child);
|
||||||
|
LostFocusEvent.AddHandler(OnMainElementLostFocus, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnMainElementLostFocus(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var newFocus = TopLevel.GetTopLevel(this)?.FocusManager?.GetFocusedElement();
|
||||||
|
if (newFocus is Visual v && _popup?.IsInsidePopup(v) == true) return;
|
||||||
|
SetCurrentValue(IsDropdownOpenProperty, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMainElementGotFocus(object sender, GotFocusEventArgs e)
|
||||||
|
{
|
||||||
|
SetCurrentValue(IsDropdownOpenProperty, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TeardownChildrenEventSubscriptions(Control? child, PopConfirmTriggerMode mode)
|
||||||
|
{
|
||||||
|
if (child is null) return;
|
||||||
|
PointerPressedEvent.RemoveHandler(OnMainElementPressed, child);
|
||||||
|
Button.ClickEvent.RemoveHandler(OnMainButtonClicked, child);
|
||||||
|
GotFocusEvent.RemoveHandler(OnMainElementGotFocus, child);
|
||||||
|
LostFocusEvent.RemoveHandler(OnMainElementLostFocus, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMainButtonClicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SetCurrentValue(IsDropdownOpenProperty, !IsDropdownOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnMainElementPressed(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
SetCurrentValue(IsDropdownOpenProperty, !IsDropdownOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
_childChangeDisposable?.Dispose();
|
_childChangeDisposable?.Dispose();
|
||||||
|
|||||||
@@ -3,6 +3,5 @@ namespace Ursa.Controls;
|
|||||||
public enum PopConfirmTriggerMode
|
public enum PopConfirmTriggerMode
|
||||||
{
|
{
|
||||||
Tap,
|
Tap,
|
||||||
Hover,
|
|
||||||
Focus,
|
Focus,
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user