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;
}
}