也就是说,事件是由于用户交互而引发的,还是由于它所绑定的属性发生了变化?
在ComboBox.SelectionChanged事件中,发送方始终是ComboBox,SelectionChangedEventArgs中没有任何内容可以帮助您.我遇到了两种解决方案.您可以在绑定上使用转换器,或者您可以检查堆栈跟踪以查看System.Windows.Controls.Primitives.Selector.OnSelectedItemsCollectionChanged(object,NotifyCollectionChangedArgs)是否在堆栈中.堆栈检查非常难看,这是一种不好的做法,并且在部分信任环境中不起作用.所以我只会描述另一个.
在绑定上使用转换器来检测更改源
此解决方案相对干净,但需要更改绑定.当事情没有改变时,它有时会通知你.
步骤1:创建一个不进行转换但具有“已转换”事件和“ConvertedBack”事件的转换器:
public EventingConverter : IValueConverter { public event EventHandler Converted; public event EventHandler ConvertedBack; public object Convert(object value, ...) { if(Converted!=null) Converted(this, EventArgs.Empty); return value; } public object ConvertBack(object value, ...) { if(ConvertedBack!=null) ConvertedBack(this, EventArgs.Empty); return value; } }
步骤2:设置绑定以使用此转换器的新实例(不要像通常那样使用资源字典或静态属性共享转换器实例)
<ComboBox ...> <ComboBox.SelectedValue> <Binding Path="..." ...> <Binding.Converter> <local:EventingConverter Converted="ComboBoxSelectedValue_Converted" ConvertedBack="ComboBoxSelectedValue_ConvertedBack" /> </Binding.Converter> </Binding> </ComboBox.SelectedValue> </ComboBox>
现在,您将从绑定过程中调用ComboBoxSelectedValue_Converted和ComboBoxSelectedValue_ConvertedBack方法.
警告:如果在这些事件中抛出异常,则会破坏绑定.
如果您无法修改执行绑定的XAML
如果您无法控制创建绑定的XAML(例如,您正在使用附加属性),您仍然可以进入并在事后添加转换器.在这种情况下,您的转换器类将需要链接到先前声明的转换器,您将必须克隆Binding并安装新的(它们在使用后它们是不可变的),并且您还必须处理MultiBindings (如果你想支持他们).
最后的说明
确定用户或财产是否进行更改的需要实际上可能是UI设计不佳的症状,通常是由于用户并不真正理解他们自己的要求.
我已经完成了几个项目,最终用户指定在“更改此ComboBox时”会发生这样的事情.几乎在所有情况下,事实证明应用程序在某些用例中会出现意外行为,我们找到了更好的方法来实现目标.在许多情况下,用户真正想要的是“当此值首先与数据库中的值不同”或“当此值不再是默认值时”或“此值为5时”.