Cancel combobox selection in WPF with MVVM

后端 未结 12 1464
你的背包
你的背包 2020-12-08 10:23

I\'ve got a combobox in my WPF application:



        
12条回答
  •  自闭症患者
    2020-12-08 11:08

    To achieve this under MVVM....

    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] Hence we configure the ComboBox.SelectedValue binding to be TwoWay and Explicit.

    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.


    In my example below, I have a list of KeyValuePair bound to the data context of the window. The ComboBox.SelectedValue is bound to a simple writeable MyKey property of the Window.

    XAML ...

        
        
    

    Where MyDGSampleWindow is the x:Name of the Window.

    Code Behind ...

    public partial class Window1 : Window
    {
        private List> list1;
    
        public int MyKey
        {
            get; set;
        }
    
        public Window1()
        {
            InitializeComponent();
    
            list1 = new List>();
            var random = new Random();
            for (int i = 0; i < 50; i++)
            {
                list1.Add(new KeyValuePair(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) 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;
                    }
                }
            }
        }
    }
    

    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.

提交回复
热议问题