/ Wpf

FocusShortcutBehavior

This behavior might be useful when you need to focus an element using a keyboard shortcut. For example, you need to focus a search box when user presses Ctrl+F. Using this behavior it can be done like this:

<TextBox x:Name="searchTextBox"
    ...>
    <i:Interaction.Behaviors>
        <Behaviors:FocusShortcutBehavior Key="F" Modifiers="Control"/>
    </i:Interaction.Behaviors>
</Controls:SearchTextBox>

Also, when the element was focused using this behavior, pressing ESC will return the focus to the element that was focused before.

Here is the source code of the behavior:

/// <summary>
/// A behavior that provides ability to specify a shortcut to focus 
/// the element to which the
/// behavior is attached.
/// </summary>
/// <remarks>
/// When element is focused using the shortcut, pressing ESC will 
/// return focus to the element that
/// was focused before.
/// </remarks>
public class FocusShortcutBehavior : Behavior<UIElement> {
 
    public ModifierKeys Modifiers { get; set; }
    public Key Key { get; set; }
 
    private DelegateCommand ShortcutCommand { get; set; }
    private DelegateCommand EscapeCommand { get; set; }
    private IInputElement PreviouslyFocusedElement { get; set; }
 
    protected override void OnAttached() {
        base.OnAttached();
 
        // Find root visual
        var root = AssociatedObject.GetAncestor<UIElement>(
                       e => VisualTreeHelper.GetParent(e) == null);
 
        // Add key binding to the root element
        ShortcutCommand = new DelegateCommand(OnShortcutPressed);
        root.InputBindings.Add(
            new InputBinding(ShortcutCommand,new KeyGesture(Key, Modifiers)));
         
        // Hook up ESC shortcut for the element to return focus to 
        // the previous focused element
        EscapeCommand = new DelegateCommand(OnEscapePressed);
        AssociatedObject.InputBindings.Add(
            new InputBinding(EscapeCommand, new KeyGesture(Key.Escape)));
    }
 
    private void OnEscapePressed() {
        Keyboard.Focus(PreviouslyFocusedElement);
    }
 
    private void OnShortcutPressed() {
        // Save previously focused element to restore focus to it 
        // if user presses ESC
        PreviouslyFocusedElement = Keyboard.FocusedElement;
 
        Keyboard.Focus(AssociatedObject);
    }
}

And here is the source code the GetAncestor extension method used in line 22:

public static T GetAncestor<T>(this DependencyObject obj,       
    Predicate<T> condition) where T : class
{
    T result = default(T);
 
    var ancestor = VisualTreeHelper.GetParent(obj);
 
    if (ancestor == null)
    {
        return result;
    }
 
 
    var candidate = VisualTreeHelper.GetParent(obj) as T;
 
    if (candidate != null && condition(candidate))
    {
        return candidate;
    }
 
    return GetAncestor(ancestor, condition);
}
Pavlo Glazkov

Pavlo Glazkov

Programmer. Full stack, with a focus on UI. JavaScript/TypeScript, Angular, Node.js, .NET

Read More