C#ListBox来自对象列表(更深)

时间:2010-11-04 13:56:54

标签: c# wpf arrays list listbox

考虑一个书架,它有架子,每个架子上都有许多书。反过来,每本书都有一些属性,如标题和作者,也许还有ISBN。

namespace mySillyExample
{
  public class BookShelf
  { 
    public Shelf[] myShelves{get; set;}
  }

  public class Shelf
  {
    public Book[] booksOnThisShelf{get; set;}
  }

  public class Book
  {
    public string Title {get; set;};
    public string Author{get; set;};
    public string ISBN {get; set;};
  }
}

现在我想在XAML中使用WPF列出所有标题的列表框。现在我的解决方案看起来像这样:

<ListBox Height="154" HorizontalAlignment="Left" 
         ItemsSource="{Binding Path=BookShelf.myShelves}"                  
         Margin="171,475,0,0" VerticalAlignment="Top" Width="333" >
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Path=booksOnThisShelf.[0].Title}" />
    </DataTemplate>
  <ListBox.ItemTemplate>
</ListBox>

我确实得到了一个包含该数据的列表框。我在上述解决方案中看到了三个问题。

  1. DataTemplate标记似乎旨在更改列表框将包含的控件类型,而不是在使用时提供其他绑定范围

  2. 我似乎在引用每个书架的书籍数组中的第0个(第0个/第一个)元素(“booksOnThisShelf。[0]”)这似乎是最邪恶的,因为它似乎不是什么如果我确实得到了我所有书的清单(我这样做)

  3. 这似乎适用于2层列表,但是3或4或42呢?

  4. 请记住,我无法直接更改类(它们是在XSD中生成的),尽管辅助类的潜力不一定是不可能的。

    我越是想到这个问题,我就越相信它会越来越多,特别是在处理复杂XML结构的数据时(网页?给我img标签的所有网址等)

    总而言之,这就是我要找的东西:

    1. 处理上述问题的最佳方法是什么?
      • 最优雅/可重复使用的型号,最好以XAML维护
    2. 如何将其抽象为n-layered列表(包含对象列表的对象包含对象列表... ad infinitum / nauseam)?
      • 使用我的示例,如果您有一个包含多个BookShelves的Room类,一个包含多个Rooms的Library类和一个包含多个Libraries的City类,该怎么办?
    3. 一如既往地提前感谢!

      注意:我使用了术语“列表”,代码显示了一个数组,我为混淆道歉

3 个答案:

答案 0 :(得分:2)

要显示所有标题,您可以创建一个静态类/方法来递归整理所有标题并返回一个平面列表。在XAML中,您可以使用配置为调用它的ObjectDataProvider(类型T上的静态方法X)来获取可以设置为列表框的ItemsSource值的列表。

答案 1 :(得分:2)

我建议看一下MVVM模式。您没有绑定到模型,但绑定到ViewModel。您的ViewModel将帮助您获得巨大的列表。你可能想要这样做:

//ViewModelBase should be a base class that implements INotifyPropertyChanged
public class MyViewModel : ViewModelBase
{
     public readonly IDataProvider _provider;

     public MyViewModel(IDataProvider provider)
     {
         _provider = provider ?? (some default provider);
     }

     public IList<String> Titles
     {
         get
         {
              var q = from shelves in _provider.GetBookShelves()
                      from books in shelves.booksOnThisShelf
                      select books.Title;

              return q as List<String>;
         }
     }
}

然后你只需要将MyViewModel设置为DataContext并绑定到标题。当然,你没有必须传递IDataProvider,你可以传入BookShelves列表,但最好让DataProvider为你获取你的模型信息。

答案 2 :(得分:0)

您也可以这样做

<ListBox Height="154" HorizontalAlignment="Left" 
         ItemsSource="{Binding Path=BookShelf.myShelves}"
         DisplayMemberPath="Title"                  
         Margin="171,475,0,0" VerticalAlignment="Top" Width="333" >
</ListBox>