使用 MVVM 在 WPF 中取消组合框选择 [英] Cancel combobox selection in WPF with MVVM
问题描述
我的 WPF 应用程序中有一个组合框:
I've got a combobox in my WPF application:
<ComboBox ItemsSource="{Binding CompetitorBrands}" DisplayMemberPath="Value"
SelectedValuePath="Key" SelectedValue="{Binding Path=CompMfgBrandID, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" Text="{Binding CompMFGText}"/>
绑定到KeyValuePair
这是我的 ViewModel 中的 CompMfgBrandID 属性:
Here is the CompMfgBrandID property in my ViewModel:
public string CompMfgBrandID
{
get { return _compMFG; }
set
{
if (StockToExchange != null && StockToExchange.Where(x => !string.IsNullOrEmpty(x.EnteredPartNumber)).Count() > 0)
{
var dr = MessageBox.Show("Changing the competitor manufacturer will remove all entered parts from the transaction. Proceed?",
"Transaction Type", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dr != DialogResult.Yes)
return;
}
_compMFG = value;
StockToExchange.Clear();
...a bunch of other functions that don't get called when you click 'No'...
OnPropertyChanged("CompMfgBrandID");
}
}
如果您选择是",它将按预期运行.项目被清除,其余的函数被调用.如果我选择否",它会返回并且不会清除我的列表或调用任何其他函数,这很好,但组合框仍会显示新选择.当用户选择否"时,我需要它恢复到原始选择,就好像什么都没有改变一样.我怎样才能做到这一点?我还尝试在代码隐藏中添加 e.Handled = true
,但无济于事.
If you choose "yes", it behaves as expected. Items are cleared and the remaining functions are called. If I choose 'No', it returns and doesn't clear my list or call any of the other functions, which is good, but the combobox still displays the new selection. I need it to revert back to the original selection, as if nothing had changed, when the user picks 'No'. How can I accomplish this? I also tried adding e.Handled = true
in codebehind, to no avail.
推荐答案
在MVVM下实现这个....
To achieve this under MVVM....
1] 具有处理 ComboBox 的 SelectionChanged
事件的附加行为.此事件由一些具有 Handled
标志的事件参数引发.但是将它设置为 true 对于 SelectedValue
绑定是没有用的.无论事件是否被处理,绑定都会更新源.
1] Have an attached behavior that handles the SelectionChanged
event of the ComboBox. This event is raised with some event args that have Handled
flag. But setting it to true is useless for SelectedValue
binding. The binding updates source irrespective of whether the event was handled.
2] 因此,我们将 ComboBox.SelectedValue
绑定配置为 TwoWay
和 Explicit
.
2] Hence we configure the ComboBox.SelectedValue
binding to be TwoWay
and Explicit
.
3] 只有当您的 check 满意并且消息框显示 Yes
时,我们才执行 BindingExpression.UpdateSource()
.否则,我们只需调用 BindingExpression.UpdateTarget()
以恢复到旧选择.
3] Only when your check is satisfied and messagebox says Yes
is when we perform BindingExpression.UpdateSource()
. Otherwise we simply call the BindingExpression.UpdateTarget()
to revert to the old selection.
在下面的示例中,我将一个 KeyValuePair
列表绑定到窗口的数据上下文.ComboBox.SelectedValue
绑定到 Window
的一个简单的可写 MyKey
属性.
In my example below, I have a list of KeyValuePair<int, int>
bound to the data context of the window. The ComboBox.SelectedValue
is bound to a simple writeable MyKey
property of the Window
.
XAML ...
<ComboBox ItemsSource="{Binding}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
SelectedValue="{Binding MyKey,
ElementName=MyDGSampleWindow,
Mode=TwoWay,
UpdateSourceTrigger=Explicit}"
local:MyAttachedBehavior.ConfirmationValueBinding="True">
</ComboBox>
其中 MyDGSampleWindow
是 x:Window
的名称.
Where MyDGSampleWindow
is the x:Name of the Window
.
背后的代码......
public partial class Window1 : Window
{
private List<KeyValuePair<int, int>> list1;
public int MyKey
{
get; set;
}
public Window1()
{
InitializeComponent();
list1 = new List<KeyValuePair<int, int>>();
var random = new Random();
for (int i = 0; i < 50; i++)
{
list1.Add(new KeyValuePair<int, int>(i, random.Next(300)));
}
this.DataContext = list1;
}
}
以及附加行为
And the attached behavior
public static class MyAttachedBehavior
{
public static readonly DependencyProperty
ConfirmationValueBindingProperty
= DependencyProperty.RegisterAttached(
"ConfirmationValueBinding",
typeof(bool),
typeof(MyAttachedBehavior),
new PropertyMetadata(
false,
OnConfirmationValueBindingChanged));
public static bool GetConfirmationValueBinding
(DependencyObject depObj)
{
return (bool) depObj.GetValue(
ConfirmationValueBindingProperty);
}
public static void SetConfirmationValueBinding
(DependencyObject depObj,
bool value)
{
depObj.SetValue(
ConfirmationValueBindingProperty,
value);
}
private static void OnConfirmationValueBindingChanged
(DependencyObject depObj,
DependencyPropertyChangedEventArgs e)
{
var comboBox = depObj as ComboBox;
if (comboBox != null && (bool)e.NewValue)
{
comboBox.Tag = false;
comboBox.SelectionChanged -= ComboBox_SelectionChanged;
comboBox.SelectionChanged += ComboBox_SelectionChanged;
}
}
private static void ComboBox_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
if (comboBox != null && !(bool)comboBox.Tag)
{
var bndExp
= comboBox.GetBindingExpression(
Selector.SelectedValueProperty);
var currentItem
= (KeyValuePair<int, int>) comboBox.SelectedItem;
if (currentItem.Key >= 1 && currentItem.Key <= 4
&& bndExp != null)
{
var dr
= MessageBox.Show(
"Want to select a Key of between 1 and 4?",
"Please Confirm.",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
if (dr == MessageBoxResult.Yes)
{
bndExp.UpdateSource();
}
else
{
comboBox.Tag = true;
bndExp.UpdateTarget();
comboBox.Tag = false;
}
}
}
}
}
在行为中,我使用 ComboBox.Tag
属性来临时存储一个标志,当我们恢复到旧的选定值时,该标志会跳过重新检查.
In the behavior I use ComboBox.Tag
property to temporarily store a flag that skips the rechecking when we revert back to the old selected value.
如果这有帮助,请告诉我.
Let me know if this helps.
这篇关于使用 MVVM 在 WPF 中取消组合框选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!