Question

My WPF application has a ListBox with lots of items in it. When the user clicks on one item with the right mouse button to open the context menu, I need to evaluate the currently selected items to build the menu item title that tells the user what happens with this command.

This command will setup a filter on the items and should indicate the resulting filter, which is based on data from the selected items, in advance.

Since I don't know of any way to get the ListBox' selected items through MVVM into the view model, I did it with code behind. The SelectionChanged event handler sends the selected items to the view model.

Unfortunately, when the user clicks fast enough, this list of selected items is outdated. I often get to see the previous selection, not the current. Only if I hold the right mouse button long enough, the selection is up-to-date.

Here's a screenshot of my test app (below):

enter image description here

Q: How can I reliably get the current selection for the context menu title?

I've made a very simple test case so you can reproduce the issue. The converter has a short delay to simulate activity. My real converter does not have this delay, but since the views are more complex, it also takes a short moment to load the UI, which has the same effect.

Here's the code: https://drive.google.com/file/d/0B8CN0ghdY1SdTW9Ka1lHc1dIUFk/edit

Was it helpful?

Solution

Update your ViewModel to this

internal class MainViewModel : INotifyPropertyChanged
{
    private List<string> _selectedItems;

    public MainViewModel()
    {
        MenuCommand = new MenuCommand();

        StringItems = new List<string>();
        StringItems.Add("Hello");
        StringItems.Add("world");
        StringItems.Add("of");
        StringItems.Add("mysterious");
        StringItems.Add("WPF");
    }

    public List<string> StringItems { get; set; }

    public MenuCommand MenuCommand { get; private set; }

    public string MenuCommandTitle
    {
        get { return "Selected items: " + SelectedItems.Aggregate((a, b) => a + ", " + b); }
    }

    public List<string> SelectedItems
    {
        get { return _selectedItems; }
        set
        {
            _selectedItems = value;
            OnPropertyChanged("MenuCommandTitle");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

You want to update the ContextMenu's binding to notify the UI of the new value.

OnPropertyChanged("MenuCommandTitle");

OTHER TIPS

It appears that your MainViewModel does not implement INotifyPropertyChanged so your MenuCommandTitle property is not always updated. And you'll need to trigger the property change when you update your SelectedItems in your code-behind.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top