【问题标题】:EventToCommand - how to prevent recursive/reentrant calls when handling selectionchangedEventToCommand - 如何在处理 selectionchanged 时防止递归/重入调用
【发布时间】:2011-08-19 20:32:22
【问题描述】:

Please see mockup code here

我正在创建一个交互式搜索页面,该页面在用户输入条件时获取数据。长话短说,我有几个组合框,它们的SelectionChanged 事件由EventToCommand 处理。

EventToCommand 在我的ViewModel 上调用一个方法,除其他外,该方法更改了多个组合框的选定项。当然,这会触发EventToCommand,整个过程会再次发生……一次又一次……一次又一次……

所以我的问题是,有没有办法让EventToCommand 真正绑定到OneWayToSource,以便源更新不会触发事件?

【问题讨论】:

  • 您是否可以执行以下操作:单击 ComboBox 时,在目标命令中设置某种标志;然后当递归返回命令时检查标志。抱歉,这些短语不完整。

标签: mvvm mvvm-light


【解决方案1】:

下面的方法 1 展示了一种可能很有价值的技术说明,但大多数应用程序可能最好使用方法 2。

方法一

作为第一种方法,我采用了 jberger 建议的方法。但是,由于我依赖于事件 args 中包含的值,并且我想根据 MVVM 目标和原则保持 View 和 ViewModel 之间的关注点分离,因此我将这个添加的逻辑放在我的代码隐藏中以保持依赖关系查看代码。

我使用了事件 args 的 AdditionalItems 内容的哈希来区分由于另一个 ComboBox 上的属性绑定而导致的“重复”调用与由于用户交互而对事件处理方法的新调用。

    int hashCode = 0;
    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      string addedItemsCatString = "";
      foreach (string item in e.AddedItems) addedItemsCatString += item;
      int newHashCode = addedItemsCatString.GetHashCode();
      if ( newHashCode == hashCode) return;
      hashCode = newHashCode;

      // execute Command code here
    }

对于一次只能选择一个项目的 ComboBox 而言,连接 AdditionalItems 的内容并不是绝对必要的,但它允许在多选控件上采用类似的方法。

方法二

由于我对方法 1 并不完全满意,我一直在思考更好的解决方案。我得到的见解是,我真的只想根据用户交互发出一次命令。键盘焦点是区分用户交互引起的 SelectionChanged 事件和属性绑定引起的事件的好标志。

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  if (!(sender as FrameworkElement).IsKeyboardFocusWithin) return;

      // execute Command code here

}

因此,上述测试可能是大多数情况的最佳解决方案,包括由不涉及任何 GUI 选择器的另一种输入模式启动 SelectionChanged 事件的情况,例如键盘快捷键或内部更改您的程序的状态 - 或者您可能执行命令的任何地方,如果您使用多个控件来控制设置,这将导致多个 SelectionChanged 事件触发。实例属性 FrameworkElement.IsKeyboardFocused 属性和静态 Keyboard.Focus(frameworkElementInstance) 方法也可能对不同的控件或场景有用。

有关键盘焦点的更多信息,请访问 msdn here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 2017-09-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多