I have three ObservableCollections: CharacterCollection, LocationCollection, and ItemCollection. They are all collections of objects; CharacterCollection is a collection of Character Objects. I need to display, in the listview, information from the collection determined by the user clicking on a button. I would prefer to use databinding, but I don't see a clear cut way to do that with multiple collections containing different types of objects. What would be the best way to easily switch between collections? 开发者_如何学JAVA
--Edit--
One of the major problems that I am having is that the different Collections each require a different number of rows and different row headers.
Just have a single IList property on your ViewModel (or code behind), like:
private IList currentCollection;
public IList CurrentCollection
{
get { return this.currentCollection; }
set
{
if (this.currentCollection != value)
{
this.currentCollection = value;
var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("CurrentCollection");
}
}
Once you've done that, when you want to switch which collection to view, just set CurrentCollection = ItemCollection;
. The DataTemplates used by the ListView can handle the different types of objects without issue.
A solution that may be even simpler than Reed Copsey's: Instead of messing around with the bindings of the ListView
s, create three different ListView
s, and have the buttons determine which one's visible. Whether I would do it this way or Reed's way depends primarily on things you haven't told us about yet.
Edit:
To answer your question, we're going to get out of "even more simple" territory, and into the territory of "why WPF is freaking awesome."
In fact, the more WPFish, MVVMish way to do things is to create a subclass for each of your three collection types - e.g. a type called CharactersCollection
that's a subclass of ObservableCollection<Character>
. Then add a DataTemplate
for each of these types to the resource dictionary:
<DataTemplate DataType="CharactersCollection">
<ListView ItemsSource="{Binding}">
<!-- specific column definitions for character information goes here -->
</ListView>
</DataTemplate>
Now, any time anything in WPF needs to render a CharactersCollection
, it'll find that template and use it.
In your view model class, you can create a property like this:
private object _ActiveCollection;
public object ActiveCollection
{
get { return _ActiveCollection; }
set
{
_ActiveCollection = value;
OnPropertyChanged("ActiveCollection");
}
}
Simple enough, right? Which collection is active? Once you've done this, anything that needs to present the ActiveCollection
property, like this:
<ContentControl Content="{Binding ActiveCollection}"/>
will render the active collection using the DataTemplate
that's appropriate for the type of active collection.
And since you've implemented INotifyPropertyChanged
, any time you set ActiveCollection
, its current value will be rendered with the appropriate template. So now all your buttons need to do is set a property on the object that's the source of the bindings. (Or be bound to Command
objects that do that, but let's walk before we run.)
The WPF CompositeCollection will handle collections containing objects of any type and is also observable.
Another option that is more strongly typed is to inherit from a common base clase for all of the collections you want to bind to. Then you can create a generic ObservableCollection propery to bind to in the form of ObservableCollection.
精彩评论