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.
While the CollectionView and ListView APIs are similar, there are some notable differences: CollectionView has a flexible layout model, which allows data to be presented vertically or horizontally, in a list or a grid. CollectionView supports single and multiple selection. CollectionView has no concept of cells.
A Xamarin. Forms ViewCell is a cell that can be added to a ListView or TableView, which contains a developer-defined view. This article demonstrates how to create a custom renderer for a ViewCell that's hosted inside a Xamarin. Forms ListView control. This stops the Xamarin.
ListView allows you to bind the data directly from the DataTable by converting the data table rows in to the collection and bind it to the ItemsSource property but the data model values is in array type, so you can directly bind the array values in the element.
The DataTemplateSelector is a class that lets you change the data template you want to use, in a ListView or CarouselView, depending upon the type of data for each item, in the list. Rather than making a complex ViewCell or ItemTemplate, you can design each one specifically for the type of data you want.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With