Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forms ListView row index

I Just started to play with Xamarin.Forms and I have a question about ListView and no answer found on the web. In the code below, I need in the ItemTemplate to get the index of the element or a way to access the ItemSource displayed in the cell, as i need to build the path of the image displayed. Better if i can have both, the index and the element. Any way without using a CustomRenderer?

ListView listView = new ListView
{
    HasUnevenRows = true,

    // Source of data items.
    ItemsSource = DataManager.GetPeople(),

    ItemTemplate = new DataTemplate(() =>
    {

        // Create views with bindings for displaying each property.
        Label nameLabel = new Label();
        nameLabel.SetBinding(Label.TextProperty, "Name");
        nameLabel.TextColor = Color.White;

        var relativeLayout = new RelativeLayout {};    

        var webImage = new Image { Aspect = Aspect.AspectFill };
        image.HeightRequest = 200;
        image.Source = ImageSource.FromFile(Path.Combine(path, "/people/263/1.jpg"));
        relativeLayout.Children.Add(image,Constraint.Constant(0),Constraint.Constant(0));

        relativeLayout.Children.Add(nameLabel,
            Constraint.RelativeToParent((parent) => {
                return parent.Width / 2 - nameLabel.Width / 2;
            }),
            Constraint.RelativeToParent((parent) =>
            {
                return parent.Height - 20;
            }));

        // Return an assembled ViewCell.
        var viewCell = new ViewCell
        {
            View = relativeLayout
        };
        viewCell.Height = 200;
        relativeLayout.HeightRequest = 200;
        return viewCell;
    })
};
like image 878
Michele Tameni Avatar asked May 01 '26 15:05

Michele Tameni


2 Answers

This can be done using a converter. You can see from the example below how to access the element BindingContext(value) and index by passing the ListView as a reference. You could use a converter to build your image path and bind it to an image source.

public class ImageSourceIndexConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || parameter == null) return Color.White;
        var index = ((ListView) parameter).ItemsSource.Cast<object>().ToList().IndexOf(value);
        return ImageSource.FromFile(Path.Combine(path, "/people/"+index+"/1.jpg"));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Then name your ListView and pass it as the parameter using x:Reference

<ListView x:Name="PeopleListView" ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}">
<ListView.ItemTemplate>
  <DataTemplate>
    <ViewCell>
      <Grid>
        <Image Source={Binding .,Converter={StaticResource StripedBackgroundIndexConverter}, ConverterParameter={x:Reference PeopleListView}}" />
      </Grid>
    </ViewCell>
  </DataTemplate>
</ListView.ItemTemplate>

like image 102
jjthemachine Avatar answered May 05 '26 03:05

jjthemachine


The "element" is the ViewCell BindingContext.

The "index" is the position of the element in the ItemsSource. If your ItemsSource is set to an List<T>, you can just use IndexOf(). If it's a true IEnumerable() you'll need to be a bit more smart. A dumb way (ok for short lists) would be:

ItemsSource.ToList().IndexOf (BindingContext);
like image 38
Stephane Delcroix Avatar answered May 05 '26 05:05

Stephane Delcroix