使用 MVVM 在 WPF 中取消组合框选择 [英] Cancel combobox selection in WPF with MVVM

查看:29
本文介绍了使用 MVVM 在 WPF 中取消组合框选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 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 绑定配置为 TwoWayExplicit.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆