Wpf 撤消组合框上的SourceUpdated绑定操作
我的Wpf 撤消组合框上的SourceUpdated绑定操作,wpf,binding,combobox,undo,Wpf,Binding,Combobox,Undo,我的组合框: <ComboBox SourceUpdated="MyComboBox_SourceUpdated" ItemsSource="{Binding ...}" SelectedValue="{Binding Path=SelectedValueMember, NotifyOnSourceUpdated=True}" SelectedValuePath="..." DisplayMemberPath="..." /> 我很难将组合框
组合框
:
<ComboBox
SourceUpdated="MyComboBox_SourceUpdated"
ItemsSource="{Binding ...}"
SelectedValue="{Binding Path=SelectedValueMember, NotifyOnSourceUpdated=True}"
SelectedValuePath="..."
DisplayMemberPath="..."
/>
我很难将组合框恢复到其原始值(在上面代码的“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线程上,它就可以工作了!我可能错了,但我的直觉是,为了避免绑定更新循环,源/目标更新处理程序中的直接操作不会被绑定响应。对于绑定中源的显式条件更新,使用updatesource触发器作为显式并处理combobox的selection changed事件,根据消息框结果执行与源的同步
<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>
这样就不需要恢复了。源显式更新,您可以对其进行所有控制。对于绑定中源的显式条件更新,使用updatesource触发器作为显式,并处理combobox的selection changed事件,根据消息框结果执行与源的同步
<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>
这样就不需要恢复了。源代码显式更新,您可以对其进行控制。使用UpdateSourceTrigger=“Explicit”添加到AngelWPF的答案中: 一种稍微简洁的方法是使用BindingExpression.UpdateSource()和BindingExpression.UpdateTarget()方法。UpdateSource()将值从UI控件移动到ViewModel,UpdateTarget()将数据移动到相反的方向。使用这些方法可以避免执行以下代码行:
((MyObject) bndExp.DataItem).MyID = (int)((ComboBox) sender).SelectedValue;
与AngelWPF的经验相反,在我的情况下,当用户取消时,即使我将Binding.UpdateSourceTrigger设置为Explicit,我也必须将ComboBox恢复为原始值。也许这是因为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();
}
}
根据需要添加您自己的空检查。使用UpdateSourceTrigger=“Explicit”添加到AngelWPF的答案: 一种稍微简洁的方法是使用BindingExpression.UpdateSource()和BindingExpression.UpdateTarget()方法。UpdateSource()将值从UI控件移动到ViewModel,UpdateTarget()将数据移动到相反的方向。使用这些方法可以避免执行以下代码行:
((MyObject) bndExp.DataItem).MyID = (int)((ComboBox) sender).SelectedValue;
与AngelWPF的经验相反,在我的情况下,当用户取消时,即使我将Binding.UpdateSourceTrigger设置为Explicit,我也必须将ComboBox恢复为原始值。也许这是因为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();
}
}
根据需要添加您自己的空检查。您是否在SelectedValueMember上引发
PropertyChanged
?或者它是一个dependencProperty
。是的,引发了PropertyChanged事件。如果我做了一个测试并连接了一个简单的按钮,其唯一目的是更改MyDataContext.SelectedValueMember的值,那么源到目标绑定工作正常,组合框会更新。下面是一个类似的问题和答案:。我认为Angel的答案可能是最好的,但是如果您不想在绑定上使用显式模式,那么使用BeginInvoke也可以。您是否在SelectedValueMember上提出PropertyChanged
?或者它是一个dependencProperty
。是的,引发了PropertyChanged事件。如果我做了一个测试并连接了一个简单的按钮,其唯一目的是更改MyDataContext.SelectedValueMember的值,那么源到目标绑定工作正常,组合框会更新。下面是一个类似的问题和答案:。我认为Angel的答案可能是最好的,但是如果您不想在绑定上使用显式模式,那么使用BeginInvoke也可以。