Xamarin.Forms: Get all cells/items of a listview

Viewed 21464

I want to make some changes to all of the cells shown in the ListView. Therefore I want to get all cells or items. E.g.

this.listView.ItemSource.Items

Items in the above code doesn't exist. Furthermore I didn't found any options on ListView or ItemSource, which could do this. Is it possible to get all cells/items? If not what other options do I have to change the appearence of the cells after they were loaded? E.g. for changing text or layout.

2 Answers

I am probably late to the party, but here's another approach using System.Reflection. Anyways, I'd suggest using it only in cases where databinding isn't possible and as a last resort option.

For a given ListView

<ListView x:Name="connectionsListView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemSelected="OnConnectionSelect">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell Height="40">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="50"/>
                    </Grid.ColumnDefinitions>
                    <customs:MyViewClass Grid.Column="0"/>
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.Footer>
        <ContentView />
    </ListView.Footer>
</ListView>

You can crawl through the ListView by grabbing the "TemplatedItems" property, casting it to ITemplatedItemsList<Cell> and iterating through your (View)cells.

IEnumerable<PropertyInfo> pInfos = (connectionsListView as ItemsView<Cell>).GetType().GetRuntimeProperties();
var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");
if (templatedItems != null)
{
  var cells = templatedItems.GetValue(connectionsListView);
    foreach (ViewCell cell in cells as Xamarin.Forms.ITemplatedItemsList<Xamarin.Forms.Cell>)
    {
        if (cell.BindingContext != null && cell.BindingContext is MyModelClass)
        {
            MyViewClass target = (cell.View as Grid).Children.OfType<MyViewClass>().FirstOrDefault();
            if (target != null)
            {
               //do whatever you want to do with your item... 
            }
        }
    }
}

Update: Since it was asked, if (cell.BindingContext != null && cell.BindingContext is MyModelClass) is basically a safeguard to prevent access to non-existing views, for instance if the ListView hasn't been populated yet.

If a check for the BindingContext being a particular model class isn't necessary, it would be sufficient to reduce the line to

if (cell.BindingContext != null)
Related