smohamed
smohamed

Reputation: 3314

How to bind a list of list to a ListView control

I have The following structure

QPage class Object contains a List<List<QLine>> QLine object contains List<Qword>

every list of words constructs a line and every list of lines consists a group(paragraph) and every list of paragraphs consists a page.

I want to bind the page to structure like this in XAML

<ListView>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <TextBlock>                 
            </TextBlock>
        </StackPanel>
    </StackPanel>
</ListView>

where each item of the ListView is a paragraph(List<QLine>) and each vertical stack panel holds an item of the List<QLine> and each item of the horizontal stack panel holds an item of the List<Qword> and the texblock is bound to Qword.text property. I have no idea how to do such binding from the XAML code.

Upvotes: 3

Views: 1637

Answers (4)

dkozl
dkozl

Reputation: 33394

Hopefully I did not miss some list but this should work. Basically it's a ListBox that hosts List<List<QLine>> (called it QPageList). Then you have ItemsControl that hosts each List<QLine> in vertical panel and finally there is another ItemsControl that hosts List<Qword> from QLine (called it QwordList) where each QWord is displayed as TextBlock on horizontal StackPanel

<!-- ItemsSource: List<List<QLine>>, Item: List<QLine> -->
<ListBox ItemsSource="{Binding QPageList}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <!-- ItemsSource: List<QLine>, Item: QLine -->
            <ItemsControl ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <!-- ItemsSource: QLine.List<QWord>, Item: QWord --> 
                        <ItemsControl ItemsSource="{Binding QwordList}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <!-- Item: QWord -->
                                    <TextBlock Text="{Binding text}"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Upvotes: 4

Subby
Subby

Reputation: 5480

Forward to what Alex is saying, it'd be a good idea to Encapsulate (If that's the correct word here) the object within classes, i.e.:

public class Page
{
    public List<Paragraph> Paragraphs { get; set; }
}

public class Paragraph
{
    public List<QWord> Sentences { get; set; }
}

public class Sentence
{
    public List<QWord> Words { get; set; }
}

That'd help when you bind data in your XAML, i.e. if you look at the tutorial which Alex provided:

<TextBlock Text="Name: " />
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text="{Binding Age}" FontWeight="Bold" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Mail}" TextDecorations="Underline" Foreground="Blue" Cursor="Hand" />
<TextBlock Text=")" />

Hope that helps you.

Upvotes: 0

BLoB
BLoB

Reputation: 9725

Hopefuly this will prove helpful. Taken from here

Authors (list)
 - - Name
 - - Books (list)
     | -  - Title
     | -  - Contents

Sample code :

  <Window.Resources>
    <DataTemplate x:Key="ItemTemplate1">
      <StackPanel>
        <TextBlock Text="{Binding Name}"/>
      </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="ItemTemplate2">
      <StackPanel>
        <TextBlock Text="{Binding Title}"/>
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource AuthorDataSource}}">
    <ListBox x:Name="AuthorList" ItemTemplate="{DynamicResource ItemTemplate1}" ItemsSource="{Binding Authors }" >
    <ListBox x:Name="BookList"  DataContext="{Binding SelectedItem, ElementName=AuthorList}" ItemsSource="{Binding Books }" ItemTemplate="{DynamicResource ItemTemplate2}" />
    <TextBlock  x:Name="BookContent"   DataContext="{Binding SelectedItem, ElementName=BookList}"  Text="{Binding Contents }" />
  </Grid>

Upvotes: 0

Alex
Alex

Reputation: 1109

What you are looking for is ListView.ItemTemplate. Basically, you need to provide your list with a way to understand the nested data structure of your rows.

Here is a good tutorial to get you started on ItemTemplates.

Once your list has an item template then you just bind the ListView directly to your data source and that's it.

Upvotes: 1

Related Questions