C# 当上下文菜单打开时,列表框所选项目未更新

C# 当上下文菜单打开时,列表框所选项目未更新,c#,wpf,mvvm,listbox,contextmenu,C#,Wpf,Mvvm,Listbox,Contextmenu,我的WPF应用程序有一个列表框,其中包含许多项。当用户用鼠标右键单击一个项目以打开上下文菜单时,我需要评估当前选定的项目以构建菜单项标题,该标题告诉用户使用此命令时会发生什么 此命令将在项目上设置过滤器,并应提前指示基于所选项目数据的结果过滤器 由于我不知道如何通过MVVM将列表框中的选定项放入视图模型中,所以我使用代码隐藏完成了这项工作。SelectionChanged事件处理程序将所选项目发送到视图模型 不幸的是,当用户足够快地单击时,所选项目的列表就过时了。我经常看到以前的选择,而不是当前

我的WPF应用程序有一个列表框,其中包含许多项。当用户用鼠标右键单击一个项目以打开上下文菜单时,我需要评估当前选定的项目以构建菜单项标题,该标题告诉用户使用此命令时会发生什么

此命令将在项目上设置过滤器,并应提前指示基于所选项目数据的结果过滤器

由于我不知道如何通过MVVM将列表框中的选定项放入视图模型中,所以我使用代码隐藏完成了这项工作。SelectionChanged事件处理程序将所选项目发送到视图模型

不幸的是,当用户足够快地单击时,所选项目的列表就过时了。我经常看到以前的选择,而不是当前的选择。只有我按住鼠标右键足够长的时间,选择才是最新的

以下是我的测试应用程序的屏幕截图(如下所示):

问:如何可靠地获取上下文菜单标题的当前选择

我制作了一个非常简单的测试用例,这样您就可以重现这个问题。转换器有一个短延迟来模拟活动。我的real converter没有这种延迟,但是由于视图更复杂,加载UI也需要很短的时间,这具有相同的效果


代码如下:

您的MainViewModel似乎没有实现,因此MenuCommandTitle属性并不总是更新。当您更新代码隐藏中的
SelectedItems
时,您需要触发属性更改。

将您的ViewModel更新为此属性

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));
    }
}

根据我的理解,每次上下文菜单打开时都会获取属性,因此它总是被回避。在这种情况下太早了。另见lll的答案。(没有-1)投了什么反对票?我给出了答案,并将OP指向我所看到的错误以及如何修复它。@LonelyPixel我调试了您的代码,发现MenuCommandTitle不是每次都被评估的。这就是INotifyPropertyChanged的用途,它将使用以前的值,除非您告诉UI它已更改。该死,您是对的!当我快速点击时,它甚至没有被抓取。很高兴知道。我已经考虑过了,但我担心上下文菜单标题在打开后立即更新时会闪烁。不过我要测试一下。好吧,效果确实出奇的好。即使长度更改,也看不到任何值更改。
OnPropertyChanged("MenuCommandTitle");