Установить фокус на другой элемент управления, когда клавиша нажата без кода позади - PullRequest
2 голосов
/ 19 августа 2011

Я реализую что-то вроде элемента управления самовнушением: у меня есть пользовательский элемент управления, который содержит TextBox и ListBox.Когда пользователь вводит текст, я передаю его с System.Windows.Interactivity поведениями и заполняю ListBox некоторыми значениями ...

Все работает нормально ... но я хочу, чтобы пользователь мог выбирать элементы вListBox (то есть для установки Focus на ListBox) при нажатии клавиши со стрелкой вниз.

Я знаю, что возможно обработать событие KeyPressDown для TextBox вфайл с выделенным кодом .cs, но как мне избежать этого?

Ответы [ 3 ]

5 голосов
/ 19 августа 2011

Если вы уже используете интерактивность, которая не должна вызывать особых проблем, просто внедрите свой собственный TriggerAction со свойствами Key & TargetName, чтобы определить, когда и на чем следует сосредоточиться. Установите его в EventTrigger для PreviewKeyDown.

Пример реализации и использования:

<TextBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewKeyDown">
            <t:KeyDownFocusAction Key="Down"
                                  Target="{Binding ElementName=lbx}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>
<ListBox Name="lbx" ItemsSource="{Binding Data}" />
class KeyDownFocusAction : TriggerAction<UIElement>
{
    public static readonly DependencyProperty KeyProperty =
        DependencyProperty.Register("Key", typeof(Key), typeof(KeyDownFocusAction));
    public Key Key
    {
        get { return (Key)GetValue(KeyProperty); }
        set { SetValue(KeyProperty, value); }
    }

    public static readonly DependencyProperty TargetProperty =
        DependencyProperty.Register("Target", typeof(UIElement), typeof(KeyDownFocusAction), new UIPropertyMetadata(null));
    public UIElement Target
    {
        get { return (UIElement)GetValue(TargetProperty); }
        set { SetValue(TargetProperty, value); }
    }

    protected override void Invoke(object parameter)
    {
        if (Keyboard.IsKeyDown(Key))
        {
            Target.Focus();
        }
    }
}

Протестировано и работает, обратите внимание, что KeyDown нет, потому что клавиши со стрелками перехвачены и помечены как обработанные TextBox.

3 голосов
/ 19 августа 2011

Я не думаю, что вы можете избежать этого

Что не так с захватом события KeyDown TextBox и, если это стрелка вверх или вниз, просто вызовите событие ListBox.KeyDown в коде позади?

Я не вижу причин не использовать выделенный код в MVVM, если он предназначен для обеспечения функциональности, специфичной для вида, например focus

0 голосов
/ 22 сентября 2015

Этот ответ основан на ответе из H.B. и добавляет поддержку проверки на предмет нажатия клавиши Ctrl.Это означает, что он может обрабатывать комбинации клавиш, такие как Ctrl-F для поиска.

XAML

<TextBox>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="PreviewKeyDown">
        <t:KeyDownFocusAction Key="Down" Ctrl="True"
                              Target="{Binding ElementName=lbx}" />
    </i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<ListBox Name="lbx" ItemsSource="{Binding Data}" />

Пространства имен

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

См. справку по добавлению System.Windows.Interactivity.

DependencyProperty

public class KeyDownFocusAction : TriggerAction<UIElement>
{
    public static readonly DependencyProperty KeyProperty =
        DependencyProperty.Register("Key", typeof(Key), typeof(KeyDownFocusAction));
    public Key Key
    {
        get { return (Key)GetValue(KeyProperty); }
        set { SetValue(KeyProperty, value); }
    }

    public static readonly DependencyProperty CtrlProperty =
        DependencyProperty.Register("Ctrl", typeof(bool), typeof(KeyDownFocusAction));
    public bool Ctrl
    {
        get { return (bool)GetValue(CtrlProperty); }
        set { SetValue(CtrlProperty, value); }
    }

    public static readonly DependencyProperty TargetProperty =
        DependencyProperty.Register("Target", typeof(UIElement), typeof(KeyDownFocusAction), new UIPropertyMetadata(null));
    public UIElement Target
    {
        get { return (UIElement)GetValue(TargetProperty); }
        set { SetValue(TargetProperty, value); }
    }

    protected override void Invoke(object parameter)
    {
        if (Keyboard.IsKeyDown(Key))
        {
            if (Ctrl == true)
            {
                if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
                {
                    Target.Focus();
                }
            }
        }
    }
}
...