I have a ListBox whose ItemSource is an ObjectDataProvider that is an instance of an ObservableCollection. The ObservableCollection is a collection of ObservableCollections. The ItemTemplate of the ListBox is a DataTemplate that creates a ListBox for each item of the listbox. To illustrate this better I'm trying to recreate a card game in WPF. Basically, from a hand of cards you can create books. After you have a valid book, you can elect to make it a book which will go into the ObservableCollection of Books. The problem that I'm having is that each item of the ListBox is a ListBox that has an ItemSource that is a Book, that is an ObservableCollection of Cards. I don't think I'm having a problem with the source or the template of the outer ListBox, but I'm having a hard time understanding how I'm going to set the source of the ListBox items to the collection of cards for each book. Essentially, my question may be confusing and a difficult concept to grasp, but essentially I'm trying to figure out how to use a ListBox in a template that will be the template of another ListBox. If anyone has any idea of how to approach this, I would greatly appreciate hearing it.
问题:
回答1:
With Card like the following:
public class Card
{
private string _name;
public Card(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
set { _name = value; }
}
}
and Book like the following:
public class Book
{
private readonly ObservableCollection<Card> _cards;
public Book(ObservableCollection<Card> cards)
{
_cards = cards;
}
public ObservableCollection<Card> Cards
{
get { return _cards; }
}
}
Then create your ListBox in the window:
<ListBox
ItemsSource="{Binding ElementName=Window, Path=Books}"
ItemTemplate="{StaticResource MainListTemplate}" />
and in the resources for the window put:
<Window.Resources>
<ResourceDictionary>
<DataTemplate
x:Key="InsideListTemplate">
<TextBlock
Text="{Binding Name}" />
</DataTemplate>
<DataTemplate
x:Key="MainListTemplate">
<ListBox
ItemsSource="{Binding Cards}"
ItemTemplate="{StaticResource InsideListTemplate}" />
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
Your ListBox uses the MainListTemplate, which contains a ListBox. The ItemsSource for that ListBox is your list of Cards, and the ItemTemplate is the InsideListTemplate. I have it as a simple TextBlock but you could do whatever you need.
回答2:
Don't put a ListBox inside a ListBox, it will create a very confusing UI because you'll have several "levels" of selected items.
You can put an ItemsControl inside a ListBox if you need a single ListBox with a collection inside each item or a ListBox inside an ItemsControl if you need multiple list boxes.
回答3:
Thank you for the responses. While I do agree with both responses, and always appreciate being notified of bad coding practices, the first answer did the trick. I was having an issue with the ItemsSource of the ListBox within my DataTemplate. Somewhere along the lines of learning WPF, I became hooked on using ObjectDataProvider(s) as my ItemsSource. Since the ObjectDataProvider was only an instance of the collection, and when I would update it the source of cards for all of my "Books" would be the same. Changing my ItemsSource binding source directly to the observable collection "Cards" did the trick.
Although it may be confusing in regards to the UI, I'm not sure that I'm going to even allow for the items in either of the lists to be selectable. My intentions were merely for a visual representation of the players books. I may need to allow for the items on the outer list to be selectable in able to move the cards from a book and back to the main hand but I'm not sure yet.
Thanks again for the help.
Thanks, Brandon