WPF自动完成框和回车键

时间:2011-02-14 20:07:03

标签: wpf autocomplete

6 个答案:

答案 0 :(得分:10)

您可以继承AutoCompleteBox,为 Enter 添加事件。

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)
{

}

答案 1 :(得分:9)

答案很晚,但是我遇到了同样的问题,这个问题让我回答了这个问题并最终使用PreviewKeyDown 解决了问题

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

private void AutoCompleteBoxName_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        //...
    }
}

答案 2 :(得分:4)

稍微容易一些(在我看来更多的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>

答案 3 :(得分:1)

(我知道这是一个迟到的答案,但我仍然认为这对想要解决这个问题的人很有用,没有代码

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"

查看

<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");
    }
}

希望这仍然可以帮助一些人。

答案 4 :(得分:0)

因此,我花了很多时间尝试使此功能生效。其他回答当然会有所帮助,并且可以带您到达目的地,但是我在实现过程中遇到以下问题:

  1. 我需要能够在ViewModel中将Enter绑定到Command的MVVM解决方案,这意味着“事件处理程序”是不受欢迎的选择。
  2. 我试图避免添加其他依赖项来修复单个控件中的单个事件,所以没有MVVMLight。

解决方案:

  1. github提取DonNetProjects.Input.Toolkit的副本
  2. 导航到AutoCompleteBox / System / Windows / Controls / 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>

产生的行为是:如果下拉列表处于打开状态,则Enter将重新路由到该对话框以完成选择;如果下拉列表处于关闭状态,则会在KeyBinding中触发命令。

答案 5 :(得分:-1)

或者,使用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)]" />

具体来说,请注意附加活动的最后一行。对于其他一些方法参数选项,请参阅here

最后,在ViewModel中定义一个公共方法:

public void AddTagOnEnter(KeyEventArgs e)
{
    if (e.Key != Key.Enter) return;
    // Do something useful
}