简体   繁体   English

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

[英]WPF Binding To Action from Parent Control's DataContext

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. 上下文菜单的父级是一个列表菜单,它将其项源绑定到UserControl中称为ActiveArtists的属性。 As so I tried to bind "back" to the original ViewModel; 因此,我尝试将“ back”绑定到原始ViewModel。 of which is a child of another ViewModel; 其中是另一个ViewModel的子级; with RelativeSource. 与RelativeSource。 However the way I did it doesn't seem to work. 但是我的方法似乎不起作用。

XAML for the tabitem XAML用于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 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: 更新2:

ViewModel used - 使用的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;
    }
}

Just set DataContext for your ContextMenu: 只需为您的ContextMenu设置DataContext:

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

Update: 更新:
DeleteArtistCommand must be a property, not a field. DeleteArtistCommand必须是属性,而不是字段。

public ICommand DeleteArtistCommand {get;set}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM