WPF autocompletebox и клавиша ввода - PullRequest
       0

WPF autocompletebox и клавиша ввода

7 голосов
/ 14 февраля 2011

Я пытаюсь заставить WPF AutoCompleteBox вызывать событие KeyDown, когда я нажимаю клавишу ввода.Я использую обычный хук KeyDown, который работает для всего, кроме клавиши ввода, кажется.Кто-нибудь знает, как я могу это исправить?

Ответы [ 6 ]

10 голосов
/ 15 февраля 2011

Вы можете унаследовать AutoCompleteBox, добавив событие для Введите .

public class MyAutoCompleteBox : AutoCompleteBox
{
    public override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        if(e.Key == Key.Enter) RaiseEnterKeyDownEvent();
    }

    public event Action<object> EnterKeyDown;
    private void RaiseEnterKeyDownEvent()
    {
        var handler = EnterKeyDown;
        if(handler != null) handler(this);
    }
}

В своем классе потребления вы можете подписаться:

public void Subscribe()
{
    autoCompleteBox.EnterKeyDown += DoSomethingWhenEnterPressed;
}

public void DoSomethingWhenEnterPressed(object sender)
{

}
9 голосов
/ 16 ноября 2013

Очень поздний ответ, но я столкнулся с той же проблемой, которая привела меня к этому вопросу и, наконец, решил его, используя PreviewKeyDown

<wpftoolkit:AutoCompleteBox Name="AutoCompleteBoxCardName"  
     Populating="LoadAutocomplete"  
     PreviewKeyDown="AutoCompleteBoxName_PreviewKeyDown"/>

и

private void AutoCompleteBoxName_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        //...
    }
}
4 голосов
/ 21 марта 2012

Там является немного более простым (и, на мой взгляд, более MVVM) способом:

// This still goes in your code behind (yuck!)
protected override void OnKeyDown(KeyEventArgs e)
        {
            if (!IsDropDownOpen && SelectedItem != null && (e.Key == Key.Enter || e.Key == Key.Return))
            {
               // Drop down is closed so the item in the textbox should be submitted with a press of the Enter key
                base.OnKeyDown(e); // This has to happen before we mark Handled = false
                e.Handled = false; // Set Handled = false so the event bubbles up to your inputbindings
                return;
            }

            // Drop down is open so user must be selecting an AutoComplete list item
            base.OnKeyDown(e);
        }

Это минимизирует кощунственное выделение кода и позволяет вашему ключевому событию продолжать пузыриться до чего-то вроде привязки ввода:

<UserControl.InputBindings>
    <KeyBinding Key="Tab" Command="{Binding NextCommand}"/>
    <KeyBinding Key="Tab" Modifiers="Shift" Command="{Binding LastCommand}"/>
    <KeyBinding Key="Escape" Command="{Binding ClearCommand}"/>
    <KeyBinding Key="Enter" Command="{Binding EnterCommand}"/>
</UserControl.InputBindings>
1 голос
/ 17 марта 2016

(я знаю, что это поздний ответ, но я все еще думаю, что он полезен для людей, которые хотят решить эту проблему, без кода )

Хороший способ сделать это в MVVM

Сначала добавьте ссылку:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

и из пакета NuGet (MVVMLight):

xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"

Чем в вашем View :

<wpftoolkit:AutoCompleteBox Name="AutoCompleteBoxName">
    <i:Interaction.Triggers>
                    <i:EventTrigger EventName="PreviewKeyDown">
                        <cmd:EventToCommand Command="{Binding AutoCompleteEnter}" PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
</wpftoolkit:AutoCompleteBox>

и чем в вашей ViewModel :

public ICommand AutoCompleteEnter { get { return new RelayCommand<System.Windows.Input.KeyEventArgs>(Auto_Complete_Enter); } }

public void Auto_Complete_Enter(System.Windows.Input.KeyEventArgs e)
{
    //Detect if key is 'Enter/Return' key
    if ((e.Key == Key.Enter) || (e.Key == Key.Return))
    {
        Console.WriteLine("U have pressed the enter key");
    }
}

Надеюсь, это все равно поможет некоторым людям.

0 голосов
/ 12 апреля 2019

Итак, я трачу много времени, пытаясь заставить эту штуку работать.Другие ответы, безусловно, полезны и приведут вас к месту назначения, но у меня есть следующие проблемы с реализацией:

  1. Мне нужно решение MVVM с возможностью привязки Enter к команде в ViewModel, что означает, что обработчики событий былинежелательный параметр.
  2. Я пытался избежать добавления дополнительных зависимостей для исправления одного события в одном элементе управления, поэтому нет MVVMLight.

Решение:

  1. Извлеките копию DonNetProjects.Input.Toolkit из github
  2. Перейдите в AutoCompleteBox / Система / Windows / Элементы управления / AutoCompleteBox.cs
  3. Изменить перегрузку метода OnKeyDown наследующее:

        if (IsDropDownOpen)
        {
            if (SelectionAdapter != null)
            {
                SelectionAdapter.HandleKeyDown(e);
                if (e.Handled)
                {
                    return;
                }
            }
    
            if (e.Key == Key.Escape)
            {
                OnAdapterSelectionCanceled(this, new RoutedEventArgs());
                //e.Handled = true;
            }
        }
        else
        {
            // The drop down is not open, the Down key will toggle it open.
            if (e.Key == Key.Down)
            {
                IsDropDownOpen = true;
                //e.Handled = true;
            }
        }
    
        // Standard drop down navigation
        switch (e.Key)
        {
            case Key.F4:
                IsDropDownOpen = !IsDropDownOpen;
                e.Handled = true;
                break;
    
            case Key.Enter:
                if (IsDropDownOpen)
                {
                    OnAdapterSelectionComplete(this, new RoutedEventArgs());
                    e.Handled = true;
                }
                break;
    
            default:
                break;
        }
    
        base.OnKeyDown(e);
    
  4. Перекомпилировать в новую DLL и ссылаться на нее вместо оригинального WPFToolkit.

Результат: Если новая версия используется следующим образом:

   xmlns:tk="clr-namespace:System.Windows.Controls;assembly=DotNetProjects.Input.Toolkit"
   <tk:AutoCompleteBox ItemsSource="{Binding AvailableValues}" SelectedItem="{Binding SelectedValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <tk:AutoCompleteBox.InputBindings>
                <KeyBinding Key="Enter" Command="{Binding AddValue}"/>
            </tk:AutoCompleteBox.InputBindings>
    </tk:AutoCompleteBox>

Результирующее поведение: если раскрывающийся список открыт, к нему будет перенаправлен ввод для завершения выбора, если раскрывающийся список закрыт, будет запущена команда в ключе.Binding.

0 голосов
/ 08 мая 2012

Кроме того, при использовании Caliburn Micro вы можете просто использовать:

<Controls:AutoCompleteBox ItemsSource="{Binding Keywords}"
                          ValueMemberPath="Name"                   
                          Text="{Binding EnteredText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                          IsTextCompletionEnabled="True"
                          cal:Message.Attach="[Event PreviewKeyDown] = [Action AddTagOnEnter($eventArgs)]" />

В частности, обратите внимание на последнюю строку, чтобы прикрепить ваше событие. Для некоторых других параметров параметров метода см. здесь .

Наконец, определите открытый метод в вашей ViewModel:

public void AddTagOnEnter(KeyEventArgs e)
{
    if (e.Key != Key.Enter) return;
    // Do something useful
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...