2

I have a List of objects that contain another List. I want to bind both Lists to different controls (one nested within the other - a ListView as GridViewItem). But I can't get the to work.

Very close to this question comes Binding List of Lists in XAML?.
And there is an article regarding this in the MSDN documentation:
How to bind to hierarchical data and create a master/details view - could be the solution, but I find it difficult to apply it to my code.
Other articles touch this topic, but not that good and also as a new user I'm not allowed to include more than two hyperlinks in a question.

My code looks similar to this (changed to city / restaurant scenario for clarity):

Model:

public class City
{
    string Name { get; set; }
    List<Restaurant> RestaurantList { get; set; }
    //.. also a constructor with parameters for the properties and an overriding toString method that returns Name
}
public class Restaurant
{
    string Name { get; set; }
    List<Uri> UriList { get; set; }
    //.. also a constructor with parameters for the properties and an overriding toString method that returns Name
}

Code-behind (LoadState method):

    //.. getting a List of cities (with restaurants), that is being created in some model class
    this.DefaultViewModel["Items"] = Cities;

Some people set the DataContext instead. I got this from the MSDN tutorials and it worked so far. But I'm not sure which is "better".

Okay now the XAML:

I want to have a GridView with the Cities as GridViewItems. Within one GridViewItem there's a Grid, displaying the City's Name in the top row and a ListView below. The ListView contains the Restaurants (only of that City!). The ListViewItems are only TextBlocks showing the Restaurant's Name. I want only the Restaurants to be clickable.

Like this:
http://imageshack.us/a/img687/5576/listviewasgridviewitem.png

<!-- the following line is at the very top and the reason why it should work without setting DataContext explicitly -->
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
<!-- ... -->
<GridView Grid.Row="1" ItemsSource="{Binding Items}" SelectionMode="None">
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Height="500" Width="200" Margin="50" Background="Gray">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="5*"/>
                </Grid.RowDefinitions>
                <TextBlock TextWrapping="Wrap" Text="{Binding Name}"/>
                <ListView
                    Grid.Row="1"
                    ItemsSource="{Binding RestaurantList}" IsItemClickEnabled="True">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}" Tapped="Restaurant_Click"/>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

This way only gray boxes are shown. When changing the TextBlock's binding to Text="{Binding}" then at least the Names of the Cities are shown. Which I don't understand and also don't want, because I guess the overriding of the toString methods is not meant to be used this way. The Names of the Restaurants don't show up in both cases.

Also, the scrolling somehow broke in this view, but that's a different story I suppose.

So: What's wrong with the data binding in the XAML?

Community
  • 1
  • 1
phlow
  • 122
  • 5
  • 12
  • Welcome on SO! The databinding needs public properties: e.g. `public string Name { get; set; }` and `public List RestaurantList { get; set; }`. Is it a "typo" in your sample or the source of your problem? – nemesv Sep 23 '12 at 16:41
  • Oh dear! That's actually it! Thanks a lot! When you make it an answer I will mark it accordingly. – phlow Sep 23 '12 at 18:53

1 Answers1

1

The databinding engine needs public properties (the link is about WPF but the same concepts apply in WinRT):

You can bind to public properties, sub-properties, as well as indexers, of any common language runtime (CLR) object.

But if you don't specify it explicit the compiler treats members by default "the most restricted access you could declare for that member" e.g. private in your case.

So you need to declare your properties as public:

public class City
{
    public string Name { get; set; }
    public List<Restaurant> RestaurantList { get; set; }
}

public class Restaurant
{
    public string Name { get; set; }
    public List<Uri> UriList { get; set; }
}
Community
  • 1
  • 1
nemesv
  • 138,284
  • 16
  • 416
  • 359