[WPF Custom Control Library] let Form automatically loaded in focus

1. Demand

After loading the first input box or let the focus is a very basic functions, such as the typical "Login" dialog. In general the "Login" dialog to load the "User Name" should immediately focus, users only need to enter a user name, click Tab, and then enter the password, click Enter to complete the login.

To make a control gets the focus when loading in WPF should be very simple, just call after the Loaded event Focus()on the line. But sometimes form is dynamically added or form elements based on the first show or hide certain conditions, it's difficult to simply let the first control has the focus.

To achieve this I created a class called FocusService tool, this article describes the principles and use of this class, as well as add some knowledge WPF focus.

2. Implement


public static readonly DependencyProperty IsAutoFocusProperty =
    DependencyProperty.RegisterAttached("IsAutoFocus", typeof(bool), typeof(FocusService), new PropertyMetadata(default(bool), OnIsAutoFocusChanged));

public static bool GetIsAutoFocus(DependencyObject obj) => (bool)obj.GetValue(IsAutoFocusProperty);

public static void SetIsAutoFocus(DependencyObject obj, bool value) => obj.SetValue(IsAutoFocusProperty, value);

private static void OnIsAutoFocusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
    var oldValue = (bool)args.OldValue;
    var newValue = (bool)args.NewValue;
    if (oldValue == newValue)
    {
        return;
    }

    if (obj is FrameworkElement target)
    {
        target.Loaded -= OnTargetLoaded;
        if (newValue)
        {
            target.Loaded += OnTargetLoaded;
        }
    }
}

private static void OnTargetLoaded(object sender, RoutedEventArgs e)
{
    var element = sender as FrameworkElement;
    if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(element))
        return;

    var request = new TraversalRequest(FocusNavigationDirection.Next);
    element.MoveFocus(request);
}

The above is FocusService code, it uses the additional attribute controls whether IsAutoFocus automatically focus, in order to make additional attributes may be controlled in XAML. This additional attribute can be used not only in the Control, can also be used on other UI elements like Grid. In the Form is provided with DefaultStyle Setter set default values, mentioned before additional properties and general properties are not dependent set default values ​​in the code.

<Setter Property="local:FocusService.IsAutoFocus"
        Value="True" />

MoveFocus

In FrameworkElement on the IsAutoFocusattached property is set to True then (False does not handle), this FrameworkElement will be called Loaded event MoveFocus function will move the keyboard focus to itself VisualTree the first element can receive focus. Specific operations generally, MoveFocus is to use a depth-first traversal of the way VisualTree, find the first IsTabStob, Focusable and IsVisible are elements of True and call Keyboard.Focusfunctions. The so-called "first" is basically intuitive and user understanding of the same.

DesignerProperties.GetIsInDesignMode

DesignerProperties.GetIsInDesignMode method for determining whether the element running in the designer. VisualStudio designer too strong, almost WYSIWYG, most of the code can be run in design view. If it is judged OnTargetLoaded running operation is not performed later in the design, a design is to avoid views are refreshed every time it receives the focus.

VisualStudio designer is really very strong, but sometimes it will program because the data is not ready, or a variety of reasons being given, if you encounter an error designer and do not want to deal with specific reasons can be considered simple and crude to use DesignerProperties.GetIsInDesignModejudgment and direct return.

3. Two types of focus

As a supplement knowledge, this article will briefly explain the focus of WPF.

3.1 keyboard focus

Refers to the current keyboard focus is receiving keyboard input UI elements. On the whole desktop, there can be only one element with keyboard focus. In order to make the UI elements get focus, Focusable and IsVisible it must be True. Typically, for a non-default attribute values ​​Focusable control class is False.

Keyboard class may be used to handle the keyboard focus, as follows:

Keyboard.Focus(FirstTextBox);

Focus function If successful, UI elements IsKeyboardFocused is set to True, and it is the parent element itself or VisualTree levels IsKeyboardFocusWithin will become True.

Of course, if the UI elements not loaded onto VisualTree Focus function does not execute successfully, it is usually only executed Focus function after the Loaded event.

3.2 logical focus

Refers to the logical focus of FocusScope FocusManager.FocusedElement , there may be a plurality of application element gets logical focus, but only one element of the keyboard focus is obtained. Element keyboard focus while also gets logical focus.

FocusScope

FocusScope by FocusManager.IsFocusScope change.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

FocusedElement

FocusManager management logic is further configured to focus, which uses GetFocusedElement (DependencyObject) acquires focus logic element FocusScope obtained using SetFocusedElement (DependencyObject, IInputElement) the focus is set to logic element.

3.3 Window logical focus of

Window default FocusScope, it is set to True (not provided in the DefaultStyle) in the static constructor function IsFocusScope:

FocusManager.IsFocusScopeProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata(true));

When loading Window (or Window itself is activated), which will allow similar code elements Window logical focus of focus.

DependencyObject doContent = Content as DependencyObject;
if (doContent != null)
{
    IInputElement focusedElement = FocusManager.GetFocusedElement(doContent) as IInputElement;
    if (focusedElement != null)
        focusedElement.Focus();
}

4. Conclusion

In fact, no class can, anyway, the code is simple, just want to pass this class was introduced to the use of additional properties and Focus.

Do custom focus manager to do, especially now, because a lot of designers, product managers, developers have a wealth of experience in mobile application development and design, due to the slightly different logical keyboard navigation on your phone and desktop applications, so the keyboard navigation details can easily be overlooked.

Often, though not with the use of easily feel someone will put forward the demand, developers always attentive to getting good keyboard navigation.

5. Reference

Focus Overview Microsoft Docs

Input Overview Microsoft Docs

FocusManager Class (System.Windows.Input) Microsoft Docs

Keyboard.Focus(IInputElement) Method (System.Windows.Input) Microsoft Docs

UIElement.MoveFocus(TraversalRequest) Method (System.Windows) Microsoft Docs

6. Source

Kino.Toolkit.Wpf_FocusService.cs

Guess you like

Origin www.cnblogs.com/dino623/p/AutoFocus.html