ItemsControl与嵌套的ComboBox - 绑定SelectedItem的位置?

时间:2014-12-12 11:39:15

标签: c# .net wpf combobox

这是我在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

2 个答案:

答案 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,添加它