소스 검색

Fix focus loss issue with AutocompleteBox (#12883)

* fix focus loss issue with autocomplete box

* close dropdown when focus actually moves within the autocompletebox's focus scope

* make GetFocusScope internal for now

* remove GetFocusScope from focus manager

---------

Co-authored-by: Max Katz <[email protected]>
Emmanuel Hansen 2 년 전
부모
커밋
11669e3a44
2개의 변경된 파일37개의 추가작업 그리고 1개의 파일을 삭제
  1. 30 1
      src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
  2. 7 0
      src/Avalonia.Controls/ListBoxItem.cs

+ 30 - 1
src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs

@@ -826,12 +826,41 @@ namespace Avalonia.Controls
             }
             else
             {
-                SetCurrentValue(IsDropDownOpenProperty, false);
+                // Check if we still have focus in the parent's focus scope
+                if (GetFocusScope() is { } scope &&
+                    (FocusManager.GetFocusManager(this)?.GetFocusedElement(scope) is not { } focused ||
+                    (focused != this &&
+                    (focused is Visual v && !this.IsVisualAncestorOf(v)))))
+                {
+                    SetCurrentValue(IsDropDownOpenProperty, false);
+                }
+
                 _userCalledPopulate = false;
                 ClearTextBoxSelection();
             }
 
             _isFocused = hasFocus;
+
+            IFocusScope? GetFocusScope()
+            {
+                IInputElement? c = this;
+
+                while (c != null)
+                {
+                    if (c is IFocusScope scope &&
+                        c is Visual v &&
+                        v.VisualRoot is Visual root &&
+                        root.IsVisible)
+                    {
+                        return scope;
+                    }
+
+                    c = (c as Visual)?.GetVisualParent<IInputElement>() ??
+                        ((c as IHostedVisualTreeRoot)?.Host as IInputElement);
+                }
+
+                return null;
+            }
         }
 
         /// <summary>

+ 7 - 0
src/Avalonia.Controls/ListBoxItem.cs

@@ -100,7 +100,14 @@ namespace Avalonia.Controls
                     ItemsControl.ItemsControlFromItemContaner(this) is ListBox owner)
                 {
                     if (owner.UpdateSelectionFromPointerEvent(this, e))
+                    {
+                        // As we only update selection from touch/pen on pointer release, we need to raise
+                        // the pointer event on the owner to trigger a commit.
+                        if (e.Pointer.Type != PointerType.Mouse)
+                            owner.RaiseEvent(e);
+
                         e.Handled = true;
+                    }
                 }
             }