下面的方法 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。