1
votes

I'm trying to bind an ObservableCollection of custom objects called ItemGroup which itself contains an ObservableCollection of Item objects (among other Properties) to a LongListSelector (to create a grouping of Item objects) in WP8.1 Silverlight:

public class Item : INotifyPropertyChanged {
    private string _name = "";
    public string Name {
        get {
            return _name;
        }
        set {
            if (value != _name) {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    private int _cost = 0;
    public int Cost {
        get {
            return _cost;
        }
        set {
            if (value != _cost) {
                _cost = value;
                NotifyPropertyChanged("Cost");
            }
        }
    }
}

public class ItemGroup : INotifyPropertyChanged {
    private string _groupName = "";
    public string GroupName {
        get {
            return _groupName;
        }
        set {
            if (value != _groupName) {
                _groupName = value;
                NotifyPropertyChanged("GroupName");
            }
        }
    }

    private int _totalCost = 0;
    public int TotalCost {
        get {
            return _totalCost;
        }
        set {
            if (value != _totalCost) {
                _totalCost = value;
                NotifyPropertyChanged("TotalCost");
            }
        }
    }

    private ObservableCollection<Item> _items = new ObservableCollection<Item>();
    public ObservableCollection<Item> Items {
        get {
            return _items;
        }
        set {
            if (value != _items) {
                _items = value;
                NotifyPropertyChanged("Items");
            }
        }
    }
}

ViewModel contains the property:

private ObservableCollection<ItemGroup> _itemGroupList = new ObservableCollection<ItemGroup>();
public ObservableCollection<ItemGroup> ItemGroupList {
    get {
        return _itemGroupList;
    }
    set {
        if (value != _itemGroupList) {
            _itemGroupList = value;
            NotifyPropertyChanged("ItemGroupList");
        }
    }
}

And the XAML:

<phone:LongListSelector ItemsSource="{Binding ItemGroupList}">

    <!-- Template for ItemGroup Items -->
    <phone:LongListSelector.ItemTemplate>
       <DataTemplate>
        <Grid Height="Auto" Margin="12,0,2,15">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <!-- Item Name  -->
            <TextBlock Text="{Binding Items.Name}" Grid.Column="0"/>

            <!-- Item Cost -->
            <TextBlock Text="{Binding Items.Cost, StringFormat='{}{0} dollars'}" Grid.Column="1"/>
        </Grid>
    </DataTemplate>
    </phone:LongListSelector.ItemTemplate>


    <!-- Template for ItemGroup headers -->
    <phone:LongListSelector.GroupHeaderTemplate>
        <DataTemplate>
            <Grid Background="#FFA2A2A2" Margin="0,10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <!-- ItemGroup Group Name -->
                <TextBlock Grid.Column="0" Text="{Binding GroupName}"/>

                <!-- ItemGroup Total Cost -->
                <TextBlock Grid.Column="1" Text="{Binding TotalCost}"/>
            </Grid>
        </DataTemplate>
    <phone:LongListSelector.GroupHeaderTemplate>
</phone:LongListSelector>

Which isn't working. The direct Properties of ItemGroup (GroupName and TotalCost) bind correctly and are visible, but no Item objects are shown! I suspect this is because I am passing to ItemTemplate the wrong source? I have tried binding the Collection directly in the LLS by ItemSource={Binding ItemGroupList.Items}, but that too doesn't work.

Update: Binding a Header control to Items.Count yields the actual number of Item objects inside Items of ItemGroup, which indicates that there indeed exists a list of Item objects for each ItemGroup.

1

1 Answers

1
votes

Note that you've got a nested collection there, so you will need 2 items controls. You can't bind to "Items.Name" or "Items.Cost" because those are not properties. You could use "Items[0].Name", but I guess that you would probably want to list all the items, something like this (inside "LongListSelector.ItemTemplate"):

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <!-- Item Name  -->
                <TextBlock Text="{Binding Items.Name}" Grid.Column="0"/>

                <!-- Item Cost -->
                <TextBlock Text="{Binding Items.Cost, StringFormat='{}{0} dollars'}" Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>