wpf - 从上下文菜单的菜单项中检索所选项目。我正在使用 WPF、MVVM

标签 wpf mvvm

我的 ListView 上有一个上下文菜单,其中 FilterBy 作为其中的菜单项之一。此菜单项绑定(bind)到一个可观察的 Menuitems 集合(_childFilterMenuitems 来自一个对象 ContextMenuclass)。我想从 FilterBy MenuItem 的子菜单中检索所选项目并绑定(bind)到我的 MainView 模型中名为 SelectedItem 的属性。

使用中继命令和填充项目一切正常。但是我无法访问我的主视图模型中的选定项目。我尝试将 SelectedItem 属性(来自 MainViewModel)绑定(bind)到 Menuitem 上的 Tag 属性。我不能让这个工作。我阅读了几个关于可视化树及其数据上下文和放置目标的博客。标签,我不知道在哪里包含标签属性。请指导我,以便我可以建立适当的绑定(bind)。我是新手,这个网站帮了我很大的忙。

在我的 MainWindow.xaml

 <ListView.ContextMenu >
   <ContextMenu Name="menuListContext" >
 <MenuItem Header="Reset" Name="menuReset" Command="{Binding ResetCmd}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}" >
<MenuItem Header="Filter By"   ItemsSource="{Binding ChildFilterMenuItems}">  
<MenuItem.ItemContainerStyle>                                   
   <Style TargetType="{x:Type MenuItem}" <Setter Property="Header" Value="{Binding  Header, Mode=TwoWay}" />  
   <Setter Property="ItemsSource" Value="{Binding Path=  ChildFilterMenuItems}"/>
   <Setter Property= "Command" Value= "{Binding DataContext.FilterByCmd, RelativeSource   ={RelativeSource AncestorType={x:Type MenuItem}}}"/>
   <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}" />
   <Setter Property="Tag" Value= "{Binding DataContext.SelectedItem, RelativeSource ={RelativeSource AncestorType=MenuItem}}"/> 
  </Style>
 </MenuItem.ItemContainerStyle>

  </ContextMenu >
</ListView.ContextMenu>

MainViewModel.xaml
  public class MainViewModel : ViewModelBase, INotifyPropertyChanged
   {
       /// <summary>
       /// The menu item selected from FilterBy Menu.
       /// </summary>
       public string SelectedItem {get;set;}

     public ObservableCollection<ContextMenuClass> ChildFilterMenuItems
     {
        get
        {
            return _childFilterMenuItems;

        }

        set
        {
            _childFilterMenuItems = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged("ChildFilterMenuItems");
        }
    }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>      
    public MainViewModel()
    {  _childFilterMenuItems = new ObservableCollection<ContextMenuClass>(); 
       //populates the menuitems for FilterBy
       PopulateFilterBy  
       FilterByCmd = new RelayCommand(() => FilterByMenu(), () => true);
    }
    private void FilterByMenu()
    {
        try
        {
          string MenuName = GetExactName(SelectedItem);
         }

上下文菜单类.cs
public class ContextMenuClass : INotifyPropertyChanged
{
    #region Fields

    private ObservableCollection<ContextMenuClass> _filterItems;

    private string _header;

    private bool _isEnabled;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the header.
    /// </summary>
    /// <value>The header.</value>
    public string Header
    {
        get
        {
            return _header;
        }
        set
        {
            _header = value; OnPropertyChanged("Header");
        }
    }



    public bool IsEnabled
    {
        get
        {
            return _isEnabled;
        }
        set
        {
             _isEnabled = value; OnPropertyChanged("IsEnabled");
        }
    }

    public ObservableCollection<ContextMenuClass> ChildFilterMenuItems
    {
        get
        {
            return (_filterItems = _filterItems ??
             new ObservableCollection<ContextMenuClass>());
        }
    }
    /// <summary>
    /// Gets or sets the SelectedItem.
    /// </summary>
    /// <value>The header.</value>
    public object SelectedMenuItem
    {
        get
        {
            return _currentItem = Header;
        }
        set
        {
            _currentItem = value; OnPropertyChanged("SelectedMenuItem");

        }

    }       
    #endregion

    #region INotifyPropertyChanged
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
    private object _currentItem;

    /// <summary>
    /// Safely raises the PropertyChanged event.
    /// </summary>
    /// <param name="property">The property name.</param>

    protected void OnPropertyChanged(string Property)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(Property));
        }
    }
    #endregion

最佳答案

如果你想知道ContextMenuClass对应于被点击的菜单项,你应该修改你的CommandParameter setter 如下:

<Setter Property="CommandParameter"
        Value="{Binding}" />

然后更改您的FilterByCmd来自 RelayCommandRelayCommand<ContextMenuClass> :
FilterByCmd = new RelayCommand<ContextMenuClass>(FilterByMenu, _ => true);

并添加 ContextMenuClass参数到您的FilterByMenu方法:
private void FilterByMenu(ContextMenuClass selectedItem)
{
    // ...
}

关于wpf - 从上下文菜单的菜单项中检索所选项目。我正在使用 WPF、MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26982258/

相关文章:

c# - 使用 Oledb 读取 Excel 文件 - 将 excel 文件的内容视为仅文本

wpf - INotifyPropertyChanged 和 DependencyProperty 有什么关系?

c# - 如何在XAML中在Window之前声明资源?

javascript - 更改给定数据模型的 HTML 样式

c# - WPF - 隐藏 ItemsControl -> UniformGrid 中的项目基于数据绑定(bind)不占用 UI 空间

c# - WPF ListView SelectedItem 为空

c# - WPF 中的列表框分隔符和最终分隔符的省略

c# - 调用嵌入在 Winforms-Application 中的 Unity-Application 上的函数

c# - 带有混合触发器的 ListView 奇怪行为

WPF MVVM Light - SelectedItem 的绑定(bind)没有改变