WPF C# 将列表框与列表框绑定为项目
WPF C# bind listbox with listbox as items
我正在使用 Entity Framework 6 和 MVVM 开发类似于 Windows 音乐播放器的个人项目。
我创建了一个包含三个 table 的数据库:music
、playlists
和 playlists_music
。
我创建 playlists_music(连接点 table)的方式使得 entity framework 在音乐 class 中创建 ICollection<playlist>
。
我想要做的是创建一个 ListBox
,其中的项目是 ListBoxe
s(主 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>
我正在使用 Entity Framework 6 和 MVVM 开发类似于 Windows 音乐播放器的个人项目。
我创建了一个包含三个 table 的数据库:music
、playlists
和 playlists_music
。
我创建 playlists_music(连接点 table)的方式使得 entity framework 在音乐 class 中创建 ICollection<playlist>
。
我想要做的是创建一个 ListBox
,其中的项目是 ListBoxe
s(主 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>