【问题标题】:Command Executs when Enter Key is Pressed Twice按两次 Enter 键时执行命令
【发布时间】:2016-06-01 05:57:58
【问题描述】:

我有一个组合框。我有一些输入绑定如下:

<ComboBox .........>

    <ComboBox.InputBindings>
        <KeyBinding Command="{Binding DataContext.DeleteUnwantedOrderItemTransactionCommand, 
                                      RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type coreUI:UserControlViewBase}}}"
                    Gesture="Return" />
        <KeyBinding Command="{Binding DataContext.DeleteUnwantedOrderItemTransactionCommand, 
                                      RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type coreUI:UserControlViewBase}}}"
                    Gesture="Tab" />
    </ComboBox.InputBindings>

</ComboBox>

在 ViewModel 中,我的 RelayCommands 如下:

public RelayCommand DeleteUnwantedOrderItemTransactionCommand { get; set; }
public RelayCommand AddNewOrderItemTransactionCommand { get; set; }

public OrderViewModel(IEventAggregator _eventAggregator)
{
    eventAggregator = _eventAggregator;

    DeleteUnwantedOrderItemTransactionCommand = new RelayCommand(DeleteUnwantedOrderItemTransaction);
    AddNewOrderItemTransactionCommand = new RelayCommand(AddNewOrderItemTransaction);
}

protected void DeleteUnwantedOrderItemTransaction(object obj)
{
    if (!(SelectedOrderItemTransaction.ItemId > 0))
    {
        NewOrder.OrderItemTransactions.Remove(SelectedOrderItemTransaction);
    }

    if (NewOrder.OrderItemTransactions.Count == 0)
    {
        NewOrder.OrderItemTransactions.Add(new OrderItemTransaction());
    }

    eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Publish(true);
}

protected void AddNewOrderItemTransaction(object obj)
{
    if (SelectedOrderItemTransaction == NewOrder.OrderItemTransactions.Last())
        NewOrder.OrderItemTransactions.Add(new OrderItemTransaction());

    eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Publish(true);
}

然后在 CodeBehind 中:

public OrderView(OrderViewModel _viewModel, IEventAggregator _eventAggregator)
{
    InitializeComponent();
    this.DataContext = _viewModel;
    _eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Subscribe(MoveToNextUIElement);
}

void MoveToNextUIElement(bool obj)
{
    // Gets the element with keyboard focus.
    UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

    if (elementWithFocus != null)
    {
        elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
}

问题:

我在 InputBindings 中指定当用户按下 EnterTab 时,我想执行 RelayCommand 并在执行完该命令后,我想移动焦点到下一个元素。

在这种情况下:

当我按下 Tab 时,一切正常。命令被执行并且焦点移动到下一个元素。

但是当我按 Enter 1st 时间时,在 ComboBox 中选择了该项目。命令不会触发,因此,焦点不会移动到下一个元素。当我按 Enter 2nd 时,命令执行并且焦点按预期移动到下一个控件。

但我不希望这种行为。我想在按下第 1st 时间 Enter 时执行命令并将焦点移动到下一个元素。

【问题讨论】:

  • 问题是 ComboBox 正在处理键盘事件。您可能需要添加PreviewKeyDown(或PreviewKeyUp)事件,检查“Enter”键,并将其设置为已处理。不过我自己从来没有测试过。
  • @Jai 我刚才试过了。当使用 PreviewKeyDown 并捕获 Enter Key 并设置 e.Handled = true 时,My Command 停止执行。使用 PreviewKeyUp 时,我得到的行为与问题中提到的相同。

标签: c# wpf xaml combobox prism


【解决方案1】:

刚刚看了 ComboBox 源代码。

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    // Let ComboBox's original method handle it
    base.OnPreviewKeyDown(e);

    // Manually check if the ComboBox handled an "Enter" key
    // If yes, set e.Handled back to false so that Command binding can consume the same event
    Key key = e.Key;
    if (key == Key.Enter)
        e.Handled = false;
}

只是说 - 我也没有测试这个!但我认为它应该工作。如果不尝试为OnKeyDown() 也这样做。显然 ComboBox 有这两种方法,并且都调用了一个私有方法KeyDownHandler(KeyEventArgs e),我们不能覆盖它。

【讨论】:

  • 谢谢你。这完美无缺。无需重写 OnKeyDown()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2018-04-12
相关资源
最近更新 更多