C# C ListBox来自对象列表(以及更深层次的列表)

C# C ListBox来自对象列表(以及更深层次的列表),c#,wpf,arrays,list,listbox,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 Boo

考虑一个书架,它有书架,每个书架上都有很多书。反过来,每本书都有一些属性,比如标题和作者,也许还有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>
我得到了一个包含这些数据的列表框。我认为上述解决方案存在三个问题

DataTemplate标签的设计似乎是为了更改列表框将包含的控件类型,而不是在使用时提供额外的绑定范围

对于每个书架书架,我似乎引用了书籍数组中的第0个零/第一个元素。[0]这似乎是最邪恶的,因为如果我确实得到了我所做的所有书籍的列表,那么这似乎不是正在发生的事情

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

请记住,我不能直接更改类,它们是在XSD中生成的,尽管潜在的助手类并不一定是不可能的

我对这个问题思考得越多,就越确信它会出现在更多的人身上,尤其是在处理来自复杂XML结构网页的数据时?给我所有的img标签等网址

总之,以下是我想要的:

处理上述问题的最佳方式是什么? 最好在XAML中维护的最优雅/可重用的模型 如何将其抽象为包含对象列表的n层列表对象包含对象列表的对象列表。无限/令人作呕? 使用我的示例,如果您有一个包含多个书架的Room类、一个包含多个房间的Library类和一个包含多个库的City类,该怎么办。 一如既往,提前感谢


注意:我使用了术语列表,代码显示了一个数组,很抱歉混淆了

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

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

我建议查看MVVM模式。您不绑定到模型,但绑定到ViewModels。您的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,您可以输入书架列表,但最好让数据提供商为您获取模型信息。

我建议您查看MVVM模式。您不绑定到模型,但绑定到ViewModels。您的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,您可以输入书架列表,但最好让数据提供商为您获取型号信息。

您也可以这样做

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

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