Setting DataContext for ContextMenu from ItemContainer ListView?

I am using the mvvm template and it is difficult for me to determine how to set the DataContext in ContextMenu from inside the ListViews ItemContainerStyle.

I also don’t understand why ListView.ContextMenu and ListViews GridView.ColumnHeaderContextMenu can see properties and commands from my view model, but ContextMenu inside ListView.ItemContainerStyle cannot.

Error

System.Windows.Data error: 40: BindingExpression path error: AddMenuItem property not found in 'object' '' Currency '(HashCode = 43406546)'. BindingExpression: Path = AddMenuItem; DataItem = 'Currency' (HashCode = 43406546); target element is "ContextMenu" (Name = ''); target is "ItemsSource" (type "IEnumerable")

View

<!-- Removed styles for clarity. --> <UserControl> <!-- Add ElementSpy to the UserControl's rsources --> <UserControl.Resources> <framework:ElementSpy x:Key="spy" /> </UserControl.Resources> <ListView ItemsSource="{Binding Currency}"> <ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <Setter Property="ContextMenu"> <Setter.Value> <!-- 'AddMenuItem' property not found on 'object' 'Currency' --> <!-- ContextMenu ItemsSource="{Binding AddMenuItem}" / --> <!-- Use the ElementSpy resource --> <ContextMenu ItemsSource="{Binding Source={StaticResource spy}, Path=Element.DataContext.AddMenuItem}" /> </Setter.Value> </Setter> </Style> </ListView.ItemContainerStyle> <ListView.ContextMenu> <!-- Works --> <ContextMenu ItemsSource="{Binding EditMenuItem}" /> </ListView.ContextMenu> <ListView.View> <GridView> <GridView.ColumnHeaderContextMenu> <!-- Works --> <ContextMenu ItemsSource="{Binding SortMenuItem}" /> </GridView.ColumnHeaderContextMenu> <GridViewColumn Header="Code" DisplayMemberBinding="{Binding Path=Code}" /> <GridViewColumn Header="Description" DisplayMemberBinding="{Binding Path=Description}" /> <GridViewColumn Header="Exchange Rate" DisplayMemberBinding="{Binding Path=ExchangeRate}" /> </GridView> </ListView.View> </ListView> </UserControl> 

Code for

 [Export(ViewNames.CurrencyMasterView, typeof(IMasterView))] [PartCreationPolicy(CreationPolicy.Shared)] public partial class CurrencyMasterView : UserControl, IMasterView { public CurrencyMasterView() { InitializeComponent(); } [Import] private MasterViewModel ViewModel { set { this.DataContext = value; } } } 

ViewModel

 [Export(typeof(MasterViewModel))] [PartCreationPolicy(CreationPolicy.NonShared)] public class MasterViewModel : ViewModelBase { [ImportingConstructor] public MasterViewModel(IGeneralController generalController, IRegionManager regionManager) { } public ObservableCollection<Currency> Currency { get { return this.currency; } set { if (this.currency != value) { this.currency = value; this.RaisePropertyChanged(() => this.Currency); } } } public List<MenuItemMvvm> SortMenuItem { get { return this.CreateSortMenuItem(); } } public List<MenuItemMvvm> EditMenuItem { get { return this.CreateEditMenuItem(); } } public List<MenuItemMvvm> AddMenuItem { get { return this.CreateAddMenuItem(); } } private List<MenuItemMvvm> CreateEditMenuItem() { var menu = new List<MenuItemMvvm>(); menu.Add(new MenuItemMvvm("_Edit") { Command = this.EditCommand, Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Edit.png")) } }); menu.Add(new MenuItemMvvm("_Duplicate") { Command = this.DuplicateCommand, Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Copy.png")) } }); menu.Add(new MenuItemMvvm("_Delete") { Command = this.DeleteCommand, Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/POS.Modules.Core;component/Resources/Images/16X16/Delete.png")) } }); return menu; } // Other methods removed for clarity } 
+4
source share
2 answers

Kevin

This question helped me figure it out. WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4: Cannot find source for binding with link

I updated the source for everyone who has this problem.

For quick reference, this is what I did.

Add the Josh Smith ElementSpy class. Enable ElementName bindings with ElementSpy

Add ElementSpy to UserControls resources.

 <UserControl.Resources> <framework:ElementSpy x:Key="spy" /> </UserControl.Resources> 

Then bind the resource and use the Element property to bind to the DataContext and the property you selected.

 <ContextMenu ItemsSource="{Binding Source={StaticResource spy}, Path=Element.DataContext.AddMenuItem}" /> 
+1
source

you should use RelativeSource and PlacementTarget in your binding. I use the following xaml to add a context menu to set the visibility of datagrid columns.

  <DataGrid.ContextMenu> <ContextMenu> <MenuItem Header="Spalten ein-/ausblenden"> <StackPanel> <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.Columns, Mode=OneWay}" ItemTemplate="{StaticResource Visibility4DataGridColumns}" ></ItemsControl> </StackPanel> </MenuItem> </ContextMenu> </DataGrid.ContextMenu> 
0
source

Source: https://habr.com/ru/post/1346639/


All Articles