开发者

How can I bind to properties of the ViewModel and properties of collection items in the ViewModel?

I'll try and explain this as best as I can...

I'm just trying to make sense of views, view models and presenters so I created a little program to illustrate some of the ins and outs. My small application basically stores albums. The albums are listed in a combo box and I have fields for artist, genre and year, which are all text boxes. Up until now, no problems... I created a binding source 开发者_Python百科and bound it to the view model (which has properties for title, artist, genre and year) and it works as expected. I can cycle through the combo box and the various text boxes will change depending on the combo box selection.

I then decided I wanted to add a list of songs for each album, so I added a new songs property to the view model and added a data grid view to the view. This is where I became quite confused. If I bind the binding source I used for everything else to the data grid view, it obviously just wants to render the immediate fields of the view model (basically repeating what I'm displaying in the text boxes, only in a grid format).

Assuming I described the problem adequately enough, what can I do to display the album fields in the text boxes and the songs in the data grid view? I think I've come to the conclusion that I simply need a second binding source, but I'd like to avoid it if possible. I've attempted obvious things like directing the DataMember property of the data grid view to "Songs" (the property name of the songs collection in the view model) without any luck.

Could anyone point me in the right direction?


So, the ViewModel loads and readies the Models that represent Albums, and the View watches the ViewModel and presents to the users the Albums in a way they can understand.

First, let's look at the Model. You have an Album, which has one or more Songs.

public sealed class Album
{
  public string Name {get;set;}
  public string Artist {get;set;}
  public IEnumerable<Song> Songs {get;set;}
}

public sealed class Song
{
  public string Name {get;set;}
  public TimeSpan Length {get;set;}
}

The ViewModel loads up a public collection of all the Albums

public sealed class ViewModel : INotifyPropertyChanged
{
  public ObservableCollection<Album> Albums {get;set;}
  public Album SelectedAlbum {get;set;} // implement INPC for this property
}

The ViewModel is the DataContext for the View. Controls bind to Albums and SelectedAlbum. Note, if the ViewModel doesn't have to act on the SelectedAlbum, we could handle the currently selected Album all in the View. This is just an example.

<ComboBox 
    ItemsSource="{Binding Albums}" 
    SelectedItem="{Binding SelectedAlbum}" />

Your controls bind relative to SelectedAlbum in order to display information about it

<TextBlock Text="{Binding SelectedAlbum.Name}" />

Your DataGrid binds to the Songs property of the SelectedAlbum

<DataGrid ItemsSource="{Binding SelectedAlbum.Songs}" />

And everything went better than expected.


I have always accomplished this using a second BindingSource that has the first BindingSource set as the DataSource.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜