WPF C# 将列表框与列表框绑定为项目

WPF C# bind listbox with listbox as items

我正在使用 Entity Framework 6 和 MVVM 开发类似于 Windows 音乐播放器的个人项目。

我创建了一个包含三个 table 的数据库:musicplaylistsplaylists_music

我创建 playlists_music(连接点 table)的方式使得 entity framework 在音乐 class 中创建 ICollection<playlist>

我想要做的是创建一个 ListBox,其中的项目是 ListBoxes(主 ListBox 中每个项目一个 ListBox

所以我最终会得到: 主 ListBox 有播放列表和其中的歌曲数量作为 Label 和另一个 ListBox 将列出该播放列表中的所有歌曲,所有这些都在数据模板中。

我做了什么:

<ListBox ItemsSource="{Binding Playlists}"
             Background="Transparent"
             BorderThickness="0">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Label Content="{Binding playlistName}"
                           Foreground="White"></Label>
                <ListBox ItemsSource="{Binding Music}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding title}"></Label>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我觉得做的不错,所有的播放列表名称都显示出来了,问题是歌名没有出现。绑定无法正常工作。 这是视图模型:

PlaylistsView playlistsView = new PlaylistsView();

private MusicPlayerDBEntities _context = new MusicPlayerDBEntities();

/// <summary>
/// Properties for playlist view model
/// </summary>
private ObservableCollection<playlist> _playlists;
public ObservableCollection<playlist> Playlists
{
    get { return _playlists; }
    set { _playlists = value; OnPropertyChanged("Playlists"); }
}

private ObservableCollection<music> _music;
public ObservableCollection<music> Music
{
    get { return _music; }
    set { _music = value; OnPropertyChanged("Music"); }
}

private playlist _selectedPlaylist;
public playlist SelectedPlaylist
{
    get { return _selectedPlaylist; }
    set { _selectedPlaylist = value; }
}

/// <summary>
/// Reference for the DatabaseActions 
/// </summary>
public DatabaseActions databaseActions
{
    get;
    private set;
}

/// <summary>
/// Constructor
/// </summary>
private PlaylistsViewModel()
{
    databaseActions = new DatabaseActions(this);
    _context.playlist.Load();
    Playlists = _context.playlist.Local;
    _context.music.Load();
    Music = _context.music.Local;

    //foreach (var song in Music)
    //{
    //    MessageBox.Show(song.title);
    //    foreach (var playlist_music in song.playlist)
    //    {
    //        if(playlist_music.music.Contains(song))
    //        {
    //            MessageBox.Show(playlist_music.playlistName + " has " + playlist_music.playlistMusicCount.ToString() + " songs.");

    //            foreach (var playlist in playlist_music.music)
    //            {
    //                MessageBox.Show(playlist.title + " in " + playlist_music.playlistName);
    //            }
    //        }
    //        else
    //        {
    //            MessageBox.Show("hasn't playlist");
    //        }

                
                
    //    }
    //}

    //this was made just for testing purposes
    foreach(var playlist in Playlists)
    {
        MessageBox.Show(playlist.playlistName + " has " + playlist.playlistMusicCount.ToString() + " songs.");
        if(playlist.playlistIndex == 1)
        {
            foreach (var musicInPlaylist in playlist.music)
            {
                MessageBox.Show(musicInPlaylist.title);
            }
        } 
    }
}


/// <summary>
/// Singleton lazy initialization
/// </summary>
public static PlaylistsViewModel Instance { get { return Nested.instance; } }

private class Nested
{
    static Nested()
    {

    }
    internal static readonly PlaylistsViewModel instance = new PlaylistsViewModel();
    }
}

我知道绑定到 Music.title 会显示所有存在的歌曲,而不仅仅是播放列表中的歌曲,我稍后会处理,但我不知道为什么绑定没有在职的。我将 post 由 EF6 创建的 classes,它可能会有所帮助。

public partial class music
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public music()
    {
        this.playlist = new HashSet<playlist>();
    }

    public int id { get; set; }
    public Nullable<int> fileIndex { get; set; }
    public string title { get; set; }
    public string artist { get; set; }
    public string albumName { get; set; }
    public string sourceDirectory { get; set; }
    public string musicFilename { get; set; }
    public string musicCompletePath { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<playlist> playlist { get; set; }
}

public partial class playlist
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public playlist()
    {
        this.music = new HashSet<music>();
    }

    public int playlistIndex { get; set; }
    public string playlistName { get; set; }
    public Nullable<int> playlistMusicCount { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<music> music { get; set; }
}

提前致谢。

为了更加清晰,我在 xaml 中添加了注释。请仔细阅读。您的绑定无效,因此无效。

<ListBox ItemsSource="{Binding Playlists}"
         Background="Transparent"
         BorderThickness="0">
        <ListBox.ItemTemplate>
            <!--Data bound to is an item of playlists collection that is class playlist-->
            <DataTemplate>
                <StackPanel>
                    <Label Content="{Binding playlistName}"
                       Foreground="White"></Label>
                    <!--Databinding is inherited here which is instance of class playlist-->
                    <!--Your are trying to bind the "**Music**" property of PlaylistsView instead of the property "**music**" that
                    is defined in playlist class-->
                    
                    <!--This binding is invalid. hence it is not working-->
                    <!--To make it wokr, instead bind to property "**music**" from class **playlist** rather then **Music** of **PlaylistsView**-->
                    <ListBox ItemsSource="{Binding Music}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Label Content="{Binding title}"></Label>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>