我的ComboBox
:
<ComboBox
SourceUpdated="MyComboBox_SourceUpdated"
ItemsSource="{Binding ...}"
SelectedValue="{Binding Path=SelectedValueMember, NotifyOnSourceUpdated=True}"
SelectedValuePath="..."
DisplayMemberPath="..."
/>
我的SourceUpdated
处理程序:
private void MyComboBox_SourceUpdated(object sender, DataTransferEventArgs args) {
if (/* user answers no to an 'are you sure?' prompt */) {
// TODO: revert ComboBox back to original value
}
}
我很难将ComboBox恢复为原始值(在上面代码的“TODO”评论中)。
我尝试的第一个也是最明显的事情就是简单地改回DataContext的SelectedValueMember的值,假设绑定会更新ComboBox:
MyDataContext.SelectedValueMember = original_value;
当我这样做时,在调试器中我可以看到它确实更新了SelectedValueMember值,但是ComboBox没有更改回来 - 它保留了新值。
有什么想法吗?
AngelWPF的答案有效,可能是最新,最清晰的方式。
然而,我确实找到了一个非显而易见的解决方案:private void MyComboBox_SourceUpdated(object sender, DataTransferEventArgs args) {
if (/* user answers no to an 'are you sure?' prompt */) {
Dispatcher.BeginInvoke(new Action(() => {
MyDataContext.SelectedValueMember = original_value;
}));
}
}
只需通过BeginInvoke
将操作放在第二个UI线程上,它就可以了!我可能是错的,但我的预感是,为了避免绑定更新循环,直接在源/目标更新处理程序中的操作不会受到绑定的反应。
答案 0 :(得分:3)
使用UpdateSourceTrigger =“Explicit”添加到AngelWPF的答案:
稍微更简洁的方法是使用BindingExpression.UpdateSource()和BindingExpression.UpdateTarget()方法。 UpdateSource()将值从UI控件移动到ViewModel,UpdateTarget()以相反的方向移动数据。使用这些方法可以使您不必执行以下代码:
((MyObject) bndExp.DataItem).MyID = (int)((ComboBox) sender).SelectedValue;
与AngelWPF的体验相反,在我的情况下,我确实必须在用户取消时将ComboBox恢复为原始值,即使我将Binding.UpdateSourceTrigger设置为Explicit。也许这是因为Telerik RadComboBox或者之前的评论不正确,我现在不能说。但无论哪种方式,更容易阅读,代码都有效。
private void OfficeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = (RadComboBox) sender;
var binding = comboBox.GetBindingExpression(RadComboBox.SelectedValueProperty);
if(MessageBox.Show("Are you sure?", "Are you sure?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
binding.UpdateSource();
}
else
{
binding.UpdateTarget();
}
}
根据需要添加自己的空检查。
答案 1 :(得分:2)
对于显式条件更新绑定中的源,使用 updatesource触发器作为Explicit 并处理组合框的选择更改事件以执行与基于源的同步在消息框结果。
<StackPanel DataContext="{StaticResource MyObject}">
<ComboBox ItemsSource="{Binding MyData}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValue="{Binding Path=MyID,
Mode=TwoWay,
UpdateSourceTrigger=Explicit}"
SelectionChanged="ComboBox_SelectionChanged">
</ComboBox>
<TextBlock Text="{Binding Path=MyID}"/>
</StackPanel>
因此ComboBox
绑定到一组项目(称为MyData
),其中Name
和ID
为属性。 ComboBox
的选定值绑定到另一个名为MyID
的属性。现在,请注意UpdateSourceTrigger=Explicit
绑定中的SelectedValue
。
我在选择更改时同步MyID
的方式,只有当用户在消息框中选择Yes
时才会选择组合框的选定值...
private void ComboBox_SelectionChanged
(object sender, SelectionChangedEventArgs e)
{
var bndExp
= BindingOperations.GetBindingExpression(
(ComboBox) sender, Selector.SelectedValueProperty);
if (bndExp != null && bndExp.ParentBinding != null)
{
if (MessageBox.Show(
"Are you sure?",
"Sure?",
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
((MyObject) bndExp.DataItem).MyID
= (int)((ComboBox) sender).SelectedValue;
}
}
}
这种方式没有必要恢复。源明确更新,您可以完全控制它。