C# WPF MVVM上下文菜单将IsOpen绑定到模型

C# WPF MVVM上下文菜单将IsOpen绑定到模型,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个按钮,上面有关联的上下文菜单。我可以右键单击按钮并按预期显示关联菜单,但是我希望能够在另一个事件(如左键单击或拖放样式事件)后显示关联菜单 我试图通过将关联菜单的IsOpen属性绑定到视图模型来实现这一点,但这并没有按预期工作。在第一次左键单击按钮时,不会发生任何情况,尽管我可以看到视图模型上的特性,该特性已绑定到正确更新的IsOpen 如果我右键单击,菜单将正确显示,然后如果我左键单击,菜单也将显示 有没有人见过这一点,或者对更新IsOpen属性时打开contextMenu需要做什么有

我有一个按钮,上面有关联的上下文菜单。我可以右键单击按钮并按预期显示关联菜单,但是我希望能够在另一个事件(如左键单击或拖放样式事件)后显示关联菜单

我试图通过将关联菜单的IsOpen属性绑定到视图模型来实现这一点,但这并没有按预期工作。在第一次左键单击按钮时,不会发生任何情况,尽管我可以看到视图模型上的特性,该特性已绑定到正确更新的IsOpen

如果我右键单击,菜单将正确显示,然后如果我左键单击,菜单也将显示

有没有人见过这一点,或者对更新IsOpen属性时打开contextMenu需要做什么有什么想法

XAML


代码隐藏

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.Commands;

namespace PopUpTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

public class MainWindowViewModel : BaseViewModel
{
    private readonly PopupViewModel<ChildViewModel> _popupViewModel;
    private readonly DelegateCommand _displayPopupCommand;

    public MainWindowViewModel()
    {
        _popupViewModel = new PopupViewModel<ChildViewModel>(new ChildViewModel { FirstName = "John", LastName = "Doe" });
        _displayPopupCommand = new DelegateCommand(() => { PopupViewModel.IsOpen = PopupViewModel.IsOpen == false; Console.WriteLine(PopupViewModel.IsOpen); });
    }

    public ICommand DisplayPopupCommand
    {
        get { return _displayPopupCommand; }
    }

    public PopupViewModel<ChildViewModel> PopupViewModel
    {
        get { return _popupViewModel; }
    }
}

public class PopupViewModel<T> : BaseViewModel
{
    private readonly T _data;

    public PopupViewModel(T data)
    {
        _data = data;
    }

    public T Data
    {
        get { return _data; }
    }

    private bool _isOpen;
    public bool IsOpen
    {
        get { return _isOpen; }
        set
        {
            if (_isOpen != value)
            {
                _isOpen = value;
                OnPropertyChanged("IsOpen");
            }
        }
    }
}

public class ChildViewModel : BaseViewModel
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (_firstName != value)
            {
                _firstName = value;
                OnPropertyChanged("FirstName");
            }
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (_lastName != value)
            {
                _lastName = value;
                OnPropertyChanged("LastName");
            }
        }
    }

}

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用Microsoft.Practices.Prism.Commands;
命名空间弹出测试
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
}
公共类MainWindowViewModel:BaseViewModel
{
私有只读PopupViewModel _PopupViewModel;
私有只读DelegateCommand\u displayPopupCommand;
公共主窗口视图模型()
{
_popupViewModel=new popupViewModel(new ChildViewModel{FirstName=“John”,LastName=“Doe”});
_displayPopupCommand=new DelegateCommand(()=>{PopupViewModel.IsOpen=PopupViewModel.IsOpen==false;Console.WriteLine(PopupViewModel.IsOpen);});
}
公共ICommand DisplayPopupCommand
{
获取{return\u displayPopupCommand;}
}
公共PopupViewModel PopupViewModel
{
获取{return\u popupViewModel;}
}
}
公共类PopupViewModel:BaseViewModel
{
私有只读T_数据;
公共PopupViewModel(T数据)
{
_数据=数据;
}
公共T数据
{
获取{return_data;}
}
私人住宅;
公共图书馆
{
获取{return _isOpen;}
设置
{
如果(_isOpen!=值)
{
_isOpen=值;
不动产变更(“IsOpen”);
}
}
}
}
公共类ChildViewModel:BaseViewModel
{
私有字符串_firstName;
公共字符串名
{
获取{return\u firstName;}
设置
{
如果(_firstName!=值)
{
_firstName=值;
OnPropertyChanged(“名字”);
}
}
}
私有字符串_lastName;
公共字符串姓氏
{
获取{return\u lastName;}
设置
{
如果(_lastName!=值)
{
_lastName=值;
OnPropertyChanged(“姓氏”);
}
}
}
}
公共类BaseViewModel:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的无效OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

我已经能够通过向XAML引入BindingProxy来解决这个问题,如MSDN论坛上对此帖子的回答所述:

绑定代理解决了ContextMenu在右键单击后首次显示之前没有DataContext的问题

这里将进一步讨论这个问题:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.Commands;

namespace PopUpTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

public class MainWindowViewModel : BaseViewModel
{
    private readonly PopupViewModel<ChildViewModel> _popupViewModel;
    private readonly DelegateCommand _displayPopupCommand;

    public MainWindowViewModel()
    {
        _popupViewModel = new PopupViewModel<ChildViewModel>(new ChildViewModel { FirstName = "John", LastName = "Doe" });
        _displayPopupCommand = new DelegateCommand(() => { PopupViewModel.IsOpen = PopupViewModel.IsOpen == false; Console.WriteLine(PopupViewModel.IsOpen); });
    }

    public ICommand DisplayPopupCommand
    {
        get { return _displayPopupCommand; }
    }

    public PopupViewModel<ChildViewModel> PopupViewModel
    {
        get { return _popupViewModel; }
    }
}

public class PopupViewModel<T> : BaseViewModel
{
    private readonly T _data;

    public PopupViewModel(T data)
    {
        _data = data;
    }

    public T Data
    {
        get { return _data; }
    }

    private bool _isOpen;
    public bool IsOpen
    {
        get { return _isOpen; }
        set
        {
            if (_isOpen != value)
            {
                _isOpen = value;
                OnPropertyChanged("IsOpen");
            }
        }
    }
}

public class ChildViewModel : BaseViewModel
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (_firstName != value)
            {
                _firstName = value;
                OnPropertyChanged("FirstName");
            }
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (_lastName != value)
            {
                _lastName = value;
                OnPropertyChanged("LastName");
            }
        }
    }

}

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
}