I can't seem to get the binding to a command from my view model to work. The parent of the context menu which is a listmenu binds its itemssource to a property in the UserControl called ActiveArtists. As so I tried to bind "back" to the original ViewModel; of which is a child of another ViewModel; with RelativeSource. However the way I did it doesn't seem to work.
XAML for the tabitem
<TabItem DataContext="{Binding Children[1]}" Header="Database"> <Grid Background="#FFE5E5E5" IsEnabled="True"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <ListView x:Name="ArtistListView" ItemsSource="{Binding ActiveArtists}" SelectedItem="{Binding SelectedArtist}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Margin="10,10,5,10"> <ListView.ContextMenu> <ContextMenu FontSize="10"> <MenuItem Header="Delete Artist" Command="{Binding Path=DeleteArtistCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}" /> </ContextMenu> </ListView.ContextMenu> <ListView.View> <GridView> <GridViewColumn Header="Artist" DisplayMemberBinding="{Binding Name}" Width="150"/> </GridView> </ListView.View> </ListView> <ListView x:Name="listView1" ItemsSource="{Binding ActiveAlbums}" SelectedItem="{Binding SelectedAlbum}" Margin="5,10,5,10" Grid.Column="1"> <ListView.View> <GridView> <GridViewColumn Header="Album" DisplayMemberBinding="{Binding Name}" Width="150"/> </GridView> </ListView.View> </ListView> <ListView x:Name="listView2" ItemsSource="{Binding ActiveTracks}" SelectedItem="{Binding SelectedTrack}" Margin="5,10,10,10" Grid.Column="2"> <ListView.View> <GridView> <GridViewColumn Header="Track" DisplayMemberBinding="{Binding Name}" Width="150"/> </GridView> </ListView.View> </ListView> Code for the MainWindowViewModel
public class MainWindowViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private MusicLogClient _musicLog; ObservableCollection<object> _children; public ObservableCollection<object> Children { get { return _children; } } public MainWindowViewModel() { string rootPath = "C:\\Programs\\MusicLog\\UserData\\"; _musicLog = new MusicLogClient(new UserSettings(rootPath+"database.xml", rootPath+"credentials.xml")); _children = new ObservableCollection<object>(); _children.Add(new ArtistEntryViewModel(_musicLog)); _children.Add(new DatabaseViewModel(_musicLog)); } Update:
I tried implementing one of the solutions proposed but it still doesn't link to the command.
This is the updated code snippet.
<ListView.ContextMenu> <ContextMenu FontSize="10" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> <MenuItem Header="Delete Artist" Command="{Binding DeleteArtistCommand}" /> </ContextMenu> </ListView.ContextMenu> Update 2:
ViewModel used -
public class DatabaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private MusicLogClient _musicLog; public ICommand DeleteArtistCommand; private ObservableCollection<Artist> _activeArtists; public ObservableCollection<Artist> ActiveArtists { get { return _activeArtists; } set { _activeArtists = value; RaisePropertyChanged("DatabaseArtists"); } } private Artist _selectedArtist; public Artist SelectedArtist { get { return _selectedArtist; } set { _selectedArtist = value; RaisePropertyChanged("SelectedArtist"); GetDatabaseAlbums(); ActiveTracks = null; } } private ObservableCollection<Album> _activeAlbums; public ObservableCollection<Album> ActiveAlbums { get { return _activeAlbums; } set { _activeAlbums = value; RaisePropertyChanged("ActiveAlbums"); } } private Album _selectedAlbum; public Album SelectedAlbum { get { return _selectedAlbum; } set { _selectedAlbum = value; RaisePropertyChanged("SelectedAlbum"); GetDatabaseTracks(); } } private ObservableCollection<Track> _activeTracks; public ObservableCollection<Track> ActiveTracks { get { return _activeTracks; } set { _activeTracks = value; RaisePropertyChanged("ActiveTracks"); } } private Track _selectedTrack; public Track SelectedTrack { get { return _selectedTrack; } set { _selectedTrack = value; RaisePropertyChanged("SelectedTrack"); } } public DatabaseViewModel(MusicLogClient musicLog) { _musicLog = musicLog; GetDatabaseArtists(); LoadCommands(); } private void GetDatabaseArtists() { ActiveArtists = _musicLog.GetArtists().ToObservableCollection(); } private void GetDatabaseAlbums() { if (SelectedArtist != null) { ActiveAlbums = _musicLog.GetAlbums(SelectedArtist).ToObservableCollection(); } } private void GetDatabaseTracks() { if (SelectedAlbum != null) { ActiveTracks = _musicLog.GetTracks(SelectedAlbum).ToObservableCollection(); } } private void LoadCommands() { DeleteArtistCommand = new CustomCommand(DeleteArtist, CanDeleteArtist); } private void DeleteArtist(object obj) { _musicLog.RemoveArtist(SelectedArtist); } private bool CanDeleteArtist(object obj) { if (SelectedArtist != null) { return true; } return false; } }