Here is a quick example solution.
It keeps all of the data in memory (for a small set, that's OK, otherwise use a database!)
The file
"../../Library.xml"
is just the xml shown above.
using System.Collections.Generic;
using System.Windows;
using System.Xml;
using System.Xml.Linq;
namespace WpfApplication3
{
public partial class MainWindow : Window
{
public MainWindow()
{
Library = new Library();
InitializeComponent();
}
public Library Library { get; private set; }
}
public class Library
{
private List<Book> Stacks = new List<Book>();
private Dictionary<string, Author> Authors = new Dictionary<string, Author>();
public Library()
{
using (XmlReader reader = new XmlTextReader("../../Library.xml"))
{
foreach (XElement bookElement in XDocument.Load(reader).Element("Library").Elements())
{
Book aBook = new Book(bookElement.Element("Title").Value);
Stacks.Add(aBook);
foreach (var authorElement in bookElement.Elements("Author"))
{
string authorName = authorElement.Value;
Author author;
if (!Authors.TryGetValue(authorName, out author))
{
author = new Author(authorName);
Authors.Add(authorName, author);
}
aBook.Authors.Add(author);
author.Books.Add(new IndexedItem<Book>(author.Books.Count + 1, aBook));
}
}
}
}
public IEnumerable<Author> AllAuthors
{ get { return Authors.Values; } }
}
public class Book
{
public Book(string title)
{
Title = title;
Authors = new List<Author>();
}
public string Title { get; private set; }
public List<Author> Authors { get; private set; }
}
public class Author
{
public Author(string name)
{
Name = name;
Books = new List<IndexedItem<Book>>();
}
public List<IndexedItem<Book>> Books { get; private set; }
public string Name { get; private set; }
}
public class IndexedItem<T>
{
public IndexedItem(int index, T item)
{
Index = index;
Item = item;
}
public int Index { get; private set; }
public T Item { get; private set; }
}
}
And the WPF:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
Title="MainWindow"
Height="350"
Width="525"
DataContext="{Binding Path=Library, RelativeSource={x:Static RelativeSource.Self}}">
<ListBox x:Name="topBox"
ItemsSource="{Binding AllAuthors}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="Name"
Text="{Binding Path=Name}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="0,0,10,0" />
<ListBox ItemsSource="{Binding Books}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="BookNumber"
Text="{Binding Path=Index}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="10,0" />
<TextBlock x:Name="Title"
Text="{Binding Path=Item.Title}"
HorizontalAlignment="Left"
VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
Styling the output is left as an exercise for the reader. ;)