2
votes

The Structure

The scenario is that I have a Pivot where each item is the menu of a certain day. Inside that PivotItem I need to display the dishes on the menu, grouped by category (e.g. soups, desserts, ...).

I have implemented this with the MVVM-model.

I thus have the folowing models:

public class Menu{
    public string Date;
    public List<DishList> Categories;
}
public class DishList
{
    public string Category;
    public List<Dish> Dishes;
}
public class Dish
{
    public string Name;
    public string Price;
}

Edit: these are simplified here, the actual structure for each field is like this:

    private string _date;

    //Get_Set
    public string Date
    {
        get
        {
            return _date;
        }
        set
        {
            if (value != _date)
            {
                _date = value;
            }
        }
    }

So the structure would be like this: a PivotElement containt a Menu-object. Inside it, I show Categories, a number of DishLists. Inside that Dishlist, I show the Category and the different Dishes, each with it's Name and Price. A mockup to make things a bit more clear (pdf-file on SkyDrive); http://sdrv.ms/12IKlWd

I have the following viewmodel

public class MenuViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Menu> _Menus;
}

The view that should implement (the structure) of the desired layout is as following:

<phone:Pivot 
        ItemsSource="{Binding Menus}">
        <phone:Pivot.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Date}" />
            </DataTemplate>
        </phone:Pivot.HeaderTemplate>
        <phone:Pivot.ItemTemplate>
            <DataTemplate>
                <ItemsControl
                    ItemsSource="{Binding Categories}">   
                    <TextBlock
                        Text="{Binding Category}"/>
                    <ItemsControl
                        x:Name="Dishes"
                        ItemsSource="{Binding Dishes}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="300"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>

                                    <TextBlock 
                                        Grid.Column="1" 
                                        Text="{Binding Name}"/>
                                    <TextBlock 
                                        Grid.Column="2" 
                                        Text="{Binding Price}"/>
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ItemsControl>
            </DataTemplate>
        </phone:Pivot.ItemTemplate>
    </phone:Pivot>

As you can see, there's nested databinding to get to the data it needs.

The only code I then do on the page is

DataContext = App.ViewModel;

The Problem

When I launch it up, I get the correct Data displayed in the PivotItems header, and the correct number of PivotItems. Ufortunately, that's it; the content of the PivotItem stays empty. The first level of databinding thus works, but no further.

The way I was thinking

  • 1st level: each PivotItem is linked to an object of type Menu, with header Menu.Date
  • 2nd level: Inside that PivotItem I set the ItemsSource of a ItemsControl to that Menu.Categories
  • 3rd level : The ItemsSource now is Menu.Categories.Dishes

I have already searched quite a bit and fiddled around with Datacontext and ItemsSource and different kinds of "{Binding ...}", but I can't get it to work. I would like to do the binding in xaml, and not in the code-behind.

Notes

  • The only function is to display data. The data is stationary and loaded once from a file. That's why I chose ItemsControl instead of ListBox, there is no need to select anything.
  • This is a MVVM-approach to my previous question: Databinding + Dynamic Pivot
1

1 Answers

4
votes

First off, you're trying to access a private field in the title so that won't work. These also have to be properties, not fields.

<TextBlock Text="{Binding Date}" />

private string Date;

Next you're binding to Category, which is also private and not a property.

<TextBlock Text="{Binding Category}"/>

private string Category;

And you're binding to the Categories field which needs to be a property.

<ItemsControl ItemsSource="{Binding Categories}">

public List<DishList> Categories;

Even if you correct these issues, you still won't get what you want because your outer ItemsControl doesn't have an ItemTemplate.

<ItemsControl ItemsSource="{Binding Categories}">   
  <TextBlock Text="{Binding Category}"/>
  ...
</ItemsControl>

Added: Your new error is because the DataTemplate can only have one child element so you need to use a container like a StackPanel.

<ItemsControl ItemsSource="{Binding Categories}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Category}"/>
        <ItemsControl x:Name="Dishes" ItemsSource="{Binding Dishes}">
          ...
        </ItemsControl>
      </StackPanel>
     </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>