Sebastian
Sebastian

Reputation: 4811

Bind subitems along with main items to same control WPF

How can we bind an object List to a control with its main items and sub items. If the class structure is like this

public class BookChapter
{
 public string Name { get; set; }
 public List<BookPage> Pages {get; set; }
 public List<String> Questions { get; set; }

}
public class BookPage
{
    public string Id { get; set; }
    public string Name { get; set; }
    public List<String> Excercises { get; set; }
}

How can i bind it on a WPF control with ChapterName and Pages associated with every chapters in a single control.

Upvotes: 3

Views: 1465

Answers (1)

Chris
Chris

Reputation: 8656

There are a few ways to achieve this in WPF, one way would involve the use of DataTemplates to describe how you would like your objects to be displayed. Using ItemsControl or derived controls to hold display your collections:

I often separate my styles into various types to make them slightly easier to read e.g:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>

    <!-- Book Chapters -->
    <DataTemplate DataType="{x:Type local:BookChapter}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=Name}" />
            <ItemsControl ItemsSource="{Binding Path=Pages}" />
        </StackPanel>
    </DataTemplate>

    <!-- Book Pages -->
    <DataTemplate DataType="{x:Type local:BookPage}">
        <StackPanel Orientation="Horizontal" >
            <TextBlock Text="{Binding Path=Id}" Margin="5 0"/>
            <TextBlock Text="{Binding Path=Name}" Margin="5 0"/>
            <ItemsControl ItemsSource="{Binding Path=Exercises}" />
        </StackPanel>
    </DataTemplate>

</Window.Resources>
<Grid>
    <ListBox ItemsSource="{Binding Path=Chapters}" />
</Grid>

Which will produce something that looks like this (based on what I populated your objects with):enter image description here

Without templating your objects, WPF will simply display the collections as ApplicationName.ClassName - the result of ToString, templates give you the ability to define how you would like your classes to be displayed.

You can hold these templates in a separate resource file, and reuse them across your application if required. It's important to note that because I'm templating the actual Type, this template will be used whenever your objects are displayed within this particular Window, unless you specify otherwise.

You can add greater control over when/were these templates are used, by naming them, and only applying them to specific components (http://msdn.microsoft.com/en-us/library/ms742521.aspx).

Upvotes: 3

Related Questions