这是我在WPF项目中遇到的问题的简化版本。它使用MVVM和Prism,但这不是很重要。
我有两个简单的类:BookType和Book Book的书。
public class BookType
{
public int Id { get; set; }
public string TypeName {get; set;}
public static ObservableCollection<BookType> GetBookTypes()
{
ObservableCollection<BookType> bookTypes = new ObservableCollection<BookType>();
bookTypes.Add(new BookType { Id = 0, TypeName = "German" });
bookTypes.Add(new BookType { Id = 1, TypeName = "English" });
return bookTypes;
}
}
public class Book
{
public BookType BookType {get; set;}
public string Name {get; set;}
public static ObservableCollection<Book> GetBooksInEnglish()
{
var englishBookType = BookType.GetBookTypes().FirstOrDefault(bt => bt.TypeName == "English");
ObservableCollection<Book> books = new ObservableCollection<Book>();
for (int i = 1; i < 10; i++ )
books.Add(new Book { Name = String.Format("Book {0}", i), BookType = englishBookType});
return books;
}
public static ObservableCollection<Book> GetBooksInGerman()
{
var germanBookType = BookType.GetBookTypes().FirstOrDefault(bt => bt.TypeName == "German");
ObservableCollection<Book> books = new ObservableCollection<Book>();
for (int i = 1; i < 10; i++)
books.Add(new Book { Name = String.Format("Buch {0}", i), BookType = germanBookType });
return books;
}
}
ViewModel有一个Books of Books,每个KeyValuePair都包含BookType和一个Books列表:
public Dictionary<BookType, ObservableCollection<Book>> Books { get; set; }
它就像那样填充:
var bookTypes = BookType.GetBookTypes();
Books = new Dictionary<BookType, ObservableCollection<Book>>();
Books[bookTypes[0]] = Book.GetBooksInGerman();
Books[bookTypes[1]] = Book.GetBooksInEnglish();
Books Dictionary是ItemsControl的ItemsSource,带有以下模板:
<ItemsControl ItemsSource="{Binding Path=Books}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Key.TypeName}" />
<ComboBox ItemsSource="{Binding Path=Value}"
SelectedItem="{Binding ?????}"
DisplayMemberPath="Name" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
这是有效的,我在TextBlock中看到BookType.TypeName,每个ComboBox都有一个这个BookType的可用书籍列表。我的问题是:我在哪里可以将SelectedItem绑定到?我需要知道为每个BookType选择了哪本Book,如果我知道在加载ViewModel时选择了哪本Book,我必须将SelectedItem设置回ComboBox。请在View中没有代码隐藏,这一切都必须在具有某种属性的ViewModel中发生。
此致 的Heiko
答案 0 :(得分:2)
这样做的一种方法是创建一个类:
class BooksGroup{
public ObservableCollection<Book> Books { get {...} set{...} }
public Book Selected { get {...} set{...} }
}
现在改变
Books = new Dictionary<BookType, BooksGroup>();
<StackPanel>
<TextBlock Text="{Binding Key.TypeName}" />
<ComboBox ItemsSource="{Binding Path=Value.Books}"
SelectedItem="{Binding Value.Selected}"
DisplayMemberPath="Name" />
</StackPanel>
答案 1 :(得分:1)
您可以拥有包含BookType,书籍列表和SelectedBook属性的对象集合,而不是字典。
然后你要做的就是将ItemsSource绑定到这些对象的List,创建一个包含ComboBox的DataTemplate,其中ItemsSource是书籍列表,其SelectedItem是SelectedBook属性。
<ItemsControl ItemsSource="{Binding Path=BooksPerType}"><!--The list-->
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type BookPerType}"><!--The new type-->
<StackPanel>
<TextBlock Text="{Binding TypeName}" />
<ComboBox ItemsSource="{Binding Books}"
SelectedItem="{Binding SelectedBook, Mode=OneWayToSource}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type Book}">
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
编辑:在这种情况下,ComboBox必须包含一个ItemTemplate,添加它