WPF : TextBox에서 프로그래밍 방식으로 포커스를 제거하는 방법


96

내 WPF에 간단한 (적어도 그랬다고 생각한) 동작을 추가하고 싶습니다 TextBox.

사용자가 Escape 키를 누르면 TextBox편집중인 사용자가 사용자가 편집을 시작했을 때의 텍스트를 가지기를 원하고 TextBox.

편집 시작 부분에 있던 값에 대한 텍스트를 설정하는 데 문제가 없습니다.

문제는 요소의 초점을 제거하는 것입니다. 포커스를 다른 구성 요소로 옮기고 싶지 TextBox않고 포커스를 잃고 싶을뿐입니다 . 초점 TextBox을 잃을 수 있도록 초점을 설정하려면 보이지 않는 요소가 있어야 합니까?

답변:


152

.NET Framework 4에서 Keyboard.ClearFocus();


1
이것이 바로 제가 오늘 저녁 찾고 있던 것이 었습니다!
Josh

9
이것이 항상 초점을 지우는 것은 아닙니다 Keyboard.ClearFocus(). 어딘가를 클릭 한 후 코드 숨김에서 실행할 때 ListBox 내부의 AutoCompleteTextBox가 초점을 잃지 않는 문제가 있습니다.
ANeves은 SE입니다 생각하는 악

3
ClearFocus원인 GotFocus최근 집중 제어하지 화재에 다른 컨트롤이 여전히 화재 동안. 예를 들어 사용자 지정 온 스크린 키보드의 경우 큰 문제입니다. 캐럿이 사라지게하는데, 아마도 "키보드 포커스"가 수반하는 모든 것입니다. 아마도 "마우스 포커스"와 같은 것에 더 관심이있을 것입니다.
Grault

2
감사합니다 Grault, 나도 같은 문제가 있습니다. 내가 생각 해낸 최선의 방법은를 사용하여 다른 컨트롤로 초점을 이동하는 것 other.Focus()입니다.
Tor Klingberg

7
@Grault 이것은 논리적 포커스 ( GotFocus이벤트에 발생하는)가 아닌 키보드 포커스 만 지 웁니다 . 프로그램에는 항상 논리적 초점이있는 것이 있습니다. LostKeyboardFocus키보드 포커스를 지우기 전에 이벤트를 사용 하거나 포커스를 다른 요소 (논리적 포커스도 함께 이동)로 이동합니다.
Chirimorin

54

내가 사용하고있는 코드 :

// Move to a parent that can take focus
FrameworkElement parent = (FrameworkElement)textBox.Parent;
while (parent != null && parent is IInputElement && !((IInputElement)parent).Focusable)
{
    parent = (FrameworkElement)parent.Parent;
}

DependencyObject scope = FocusManager.GetFocusScope(textBox);
FocusManager.SetFocusedElement(scope, parent as IInputElement);

2
이 코드는 훌륭합니다. Keyboard.ClearFocus ()에는 의도하지 않은 부작용이 있습니다
patrick

조건! ((IInputElement) parent) .Focusable에 "!"가있는 이유 뿅? 부모가 초점을 맞출 수 있다면이 조건이 사실이 아니어야합니까?
Mert Akcakaya 2012 년

Mert-확실하지는 않지만이 게시물을 살펴보면 해당 조건이 참이 될 때까지 계속 반복하는 것처럼 보입니다. 이렇게하면 첫 번째 포커스 가능한 항목이 루프를 종료합니다.
jpierson

4
@patrick, 이는 부작용을 의도하지? 관련 예를 들어 주시겠습니까?
ANeves은 SE입니다 생각하는 악

1
이것은 훌륭한 솔루션입니다. 또한 Keyboard.ClearFocus ()에 문제가있었습니다. 모달 창 내부의 TextBox에서 ClearFocus ()를 실행하면 TextBox와 Window가 모두 포커스를 잃게됩니다. 의미 KeyDown 이벤트가 더 이상 창으로 이동하지 않습니다. 대신 Focus가 부모 (Window 일 수 있음)로 변경되도록 변경하면 향후 KeyDown 이벤트가 손실되지 않습니다. 실제 예제에서는 "Key.Escape"를 찾고 Close ()를 호출하는 Window가 있습니다. 어디에서나 ClearFocus ()를 실행하면 작동이 중지됩니다.
Denis P

19

파티에 조금 늦었지만 도움이되었으므로 여기에 있습니다.

.Net 3.0 이후 로 나를 위해 트릭을 수행 FrameworkElementMoveFocus 기능이 있습니다.



"이 메서드의 반환 값을 확인하십시오. 순회가 컨트롤의 구성에 의해 정의 된 탭 정지로 실행되고 순회 요청이 랩핑을 요청하지 않은 경우 false 반환 값이 반환 될 수 있습니다." - msdn.microsoft.com/en-us/library/...
aderesh

13

위의 답변 중 어느 것도 저에게 효과가 없었고 수락 된 답변은 키보드 포커스에서만 작동하므로 다음 접근 방식에 도달했습니다.

// Kill logical focus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(textBox), null);
// Kill keyboard focus
Keyboard.ClearFocus();

논리적이고 키보드 포커스를 모두 죽입니다.


9

포커스 가능한 상위 항목에 포커스를 설정할 수 있습니다. 이 코드는 텍스트 상자가 동일한 템플릿 내에 포커스 가능한 조상이없는 템플릿 내부에있는 경우에도 작동합니다.

DependencyObject ancestor = textbox.Parent;
while (ancestor != null)
{
    var element = ancestor as UIElement;
    if (element != null && element.Focusable)
    {
        element.Focus();
        break;
    }

    ancestor = VisualTreeHelper.GetParent(ancestor);
}

6

AFAIK, 초점을 완전히 제거하는 것은 불가능합니다. 창에있는 항목은 항상 포커스를 갖습니다.


2

Windows Phone 개발에서 방금 수행 Focus()했거나 PhoneApplicationPagethis.Focus() 에서 수행했으며 매력처럼 작동했습니다.


1

저에게는 특히 LostFocus 바인딩과 함께 사용할 때 매우 까다 롭습니다. 그러나 내 해결 방법은 빈 레이블을 추가하고 그것에 초점을 맞추는 것입니다.

<Label Name="ResetFocusArea" Focusable="True" FocusVisualStyle="{x:Null}" />

...

OnKeyDown(object sender, RoutedEventArgs e)
{
  //if is Esc
  ResetFocusArea.Focus();
}

0

내 대답은 위의 질문을 직접적으로 다루지는 않지만 그 표현이 프로그래밍 방식으로 초점을 없애는 것에 대한 "The Question"이되게 한 것 같습니다. 이것이 필요한 일반적인 시나리오는 사용자가 창과 같은 루트 컨트롤의 배경을 마우스 왼쪽 버튼으로 클릭하여 포커스를 지울 수 있도록하는 것입니다.

따라서이를 달성하기 위해 동적으로 생성 된 컨트롤 (제 경우에는 빈 레이블)로 포커스를 전환하는 Attached Behavior를 만들 수 있습니다. 더미 레이블을 추가 할 수있는 패널을 찾기 위해 하위 항목을 반복하므로 창과 같은 최상위 요소에서이 동작을 사용하는 것이 좋습니다.

public class LoseFocusOnLeftClick : Behavior<FrameworkElement>
{
    private readonly MouseBinding _leftClick;
    private readonly Label _emptyControl = new Label() { Focusable = true, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top };

    public LoseFocusOnLeftClick()
    {
        _leftClick = new MouseBinding(new RelayCommand(LoseFocus), new MouseGesture(MouseAction.LeftClick));
    }

    protected override void OnAttached()
    {
        AssociatedObject.InputBindings.Add(_leftClick);
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }        

    protected override void OnDetaching()
    {
        AssociatedObject.InputBindings.Remove(_leftClick);
        AssociatedObject.Loaded -= AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        AssociatedObject.Loaded -= AssociatedObject_Loaded;

        AttachEmptyControl();
    }

    private void AttachEmptyControl()
    {            
        DependencyObject currentElement = AssociatedObject;
        while (!(currentElement is Panel))
        {
            currentElement = VisualTreeHelper.GetChild(currentElement, 0);
        }

        ((Panel)currentElement).Children.Add(_emptyControl);
    }

    private void LoseFocus()
    {            
        _emptyControl.Focus();
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.