WPF Listbox commands

2019-07-21 06:41发布

问题:

Ok, my program in a nutshell has a list of customers. Those customers are all listed in a listbox so when one is clicked on all of their information appears on the form. This works through databinding, all of the controls on the page are bound to the listbox's selectedItem.

What I would like to do now is have a message dialog that asks if the user would like to save when they try to change the selection. If they don't I want to revert it back to the original item in the collection. If they hit cancel I want the selection to focus back on the previously selected item. I am wondering what the best way would be to accomplish this in an MVVM manner?

Currently I have a Model for my customer and my VM fills a collection of Customers that the listbox is bound to. So is there a way to handle the selection changed event on the VM that would include being able to manipulate the selectedIndex of the listbox? Here is my code so you can see what I am doing.

                if (value != _selectedAccount)
                {
                    MessageBoxResult mbr = MessageBox.Show("Do you want to save your work?", "Save", MessageBoxButton.YesNoCancel);
                    if (mbr == MessageBoxResult.Yes)
                    {
                        //Code to update corporate
                        Update_Corporate();
                        _preSelectedAccount = value;
                        _selectedAccount = value;
                    }
                    if (mbr == MessageBoxResult.No)
                    {
                        //Do Stuff

                    }
                    if (mbr == MessageBoxResult.Cancel)
                    {

                        SelectedAccount = _preSelectedAccount;
                        NotifyPropertyChanged("SelectedAccount");
                    }

                }

回答1:

XAML:

<ListBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}" DisplayMemberPath="CustomerName"/>

ViewModel:

private Customer selectedCustomer;
public Customer SelectedCustomer
{
  get
  {
    return selectedCustomer;
  }
  set
  {
    if (value != selectedCustomer)
    {
      var originalValue = selectedCustomer;
      selectedCustomer = value;
      dlgConfirm dlg = new dlgConfirm();
      var result = dlg.ShowDialog();
      if (!result.HasValue && result.Value)
      {
        Application.Current.Dispatcher.BeginInvoke(
            new Action(() =>
            {
                selectedCustomerr = originalValue;
                OnPropertyChanged("SelectedCustomer");
            }),
            System.Windows.Threading.DispatcherPriority.ContextIdle,
            null
        );
      }
      else
        OnPropertyChanged("SelectedCustomer");
    }
  }
}

Taken/further info from here.



回答2:

the best way you can catch the changed event is to bind the SelectedItem of the listbox to another property in your view model, then on the set you can do what you need to do:

private Customer selectedCustomer;
public Customer SelectedCustomer
{
    get { return selectedCustomer; }
    set
    {
        if (selectedCustomer== value) return;
        selectedCustomer = value;
        RaisePropertyChanged("SelectedCustomer");
        // Do your stuff here
    }
}

This is an example using MVVM light (RaisePropertyChanged).