我的ListView上有一个上下文菜单,其中FilterBy是其中的一个菜单项。此菜单项绑定到可观察的Menuitems集合(来自对象ContextMenuclass的_childFilterMenuitems)。我想从FilterBy MenuItem的子菜单中检索所选项目,并在我的MainView模型中绑定到名为SelectedItem的属性。
使用relay命令并填充项目,一切正常。但是,我无法访问主视图模型中的选定项目。我尝试将SelectedItem属性(从MainViewModel)绑定到Menuitem上的Tag属性。我不能让这个工作。我阅读了几篇关于可视树及其datacontext和Placement target.Tag的博客,我无法弄清楚包含tag属性的位置。请指导我,以便我可以建立适当的绑定。我很新,这个网站有很大的帮助。
<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>
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);
}
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
答案 0 :(得分:1)
如果您想知道哪个ContextMenuClass
对应于所点击的菜单项,则应修改CommandParameter
setter,如下所示:
<Setter Property="CommandParameter"
Value="{Binding}" />
然后将FilterByCmd
从RelayCommand
更改为RelayCommand<ContextMenuClass>
:
FilterByCmd = new RelayCommand<ContextMenuClass>(FilterByMenu, _ => true);
并在ContextMenuClass
方法中添加FilterByMenu
参数:
private void FilterByMenu(ContextMenuClass selectedItem)
{
// ...
}
答案 1 :(得分:0)
我希望这可以帮助:
<MenuItem ItemsSource="{Binding MyList}">
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding RelativeSource={ RelativeSource FindAncestor, AncestorType={ x:Type Window}}, Path= DataContext.MyListItemCommand}"/>
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="IsCheckable" Value="True"/>
<Setter Property="IsChecked" Value="{Binding IsChecked, Mode=OneWay}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
因此列表为 MyList
,命令为 MyListItemCommand
,命令参数为 MyList
中的实际项目(因为 Value="{Binding}"
返回实际列表项目)。< /p>
这也意味着您需要编写 MyListItemCommand
(实现 ICommand
接口)类来管理当前检查哪个列表项(请注意,也可以同时检查多个项目在这种情况下)。