WPF从父控件的DataContext绑定到操作

时间:2018-07-17 05:50:41

标签: c# wpf xaml

我似乎无法从我的视图模型中绑定到命令来工作。上下文菜单的父级是一个列表菜单,它将其项源绑定到UserControl中称为ActiveArtists的属性。因此,我尝试将“ back”绑定到原始ViewModel。其中是另一个ViewModel的子级;与RelativeSource。但是我的方法似乎无效。

用于Tabitem的XAML

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

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

更新:

我尝试实现建议的解决方案之一,但它仍未链接到命令。

这是更新的代码段。

<ListView.ContextMenu>
                    <ContextMenu FontSize="10" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                        <MenuItem Header="Delete Artist" Command="{Binding DeleteArtistCommand}" />
                    </ContextMenu>
</ListView.ContextMenu>

更新2:

使用的ViewModel-

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

1 个答案:

答案 0 :(得分:2)

只需为您的ContextMenu设置DataContext:

<ContextMenu FontSize="10" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">

更新:
DeleteArtistCommand必须是属性,而不是字段。

public ICommand DeleteArtistCommand {get;set}