【问题标题】:WPF Binding To Action from Parent Control's DataContextWPF 从父控件的 DataContext 绑定到操作
【发布时间】:2018-07-17 05:50:41
【问题描述】:

我似乎无法让我的视图模型中的命令绑定工作。作为列表菜单的上下文菜单的父级将其 itemssource 绑定到 UserControl 中称为 ActiveArtists 的属性。因此,我尝试将“返回”绑定到原始 ViewModel;其中是另一个 ViewModel 的孩子;与相对来源。但是我这样做的方式似乎不起作用。

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

更新:

我尝试实施建议的解决方案之一,但它仍然没有链接到命令。

这是更新后的代码sn-p。

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

【问题讨论】:

标签: c# wpf xaml


【解决方案1】:

只需为您的 ContextMenu 设置 DataContext:

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

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

public ICommand DeleteArtistCommand {get;set}

【讨论】:

  • 您好,我尝试实施您的解决方案,但似乎无法解决问题。
  • 你的DeleteArtistCommandActiveAlbums 是同一个班级吗?
  • 是的,我会把整个DatabaseViewModel放上来
  • 哦,拍摄,完全错过了。感谢您的帮助!
猜你喜欢
  • 2012-11-05
  • 2013-02-02
  • 2015-06-27
  • 2018-11-14
  • 2018-08-29
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多