Чередование цветов строк в Xamarin Forms ListView IOS

Я пытаюсь написать CustomRenderer, который может позволить ListView иметь чередующиеся цвета строк. У меня возникла проблема, и я не уверен, может ли это быть ошибка, или я просто неправильно реализую средство визуализации:

Я ожидаю от следующего кода, что каждая пользовательская ячейка представления должна иметь цвет в зависимости от ее положения. Однако это не то, что происходит, я считаю, что этот код tv.IndexPathForCell(cell).Row должен возвращать индекс ячейки, но он работает не так, как ожидалось. В настоящее время он возвращает нулевое значение (которое должно быть, если ячейка не является частью представления), но я считаю, что ячейка является частью представления таблицы и, следовательно, моей проблемой. Если я закомментирую var index = tv.IndexPathForCell(cell).Row;, а затем установлю для цвета фона статическое значение, код и представление будут работать правильно. Кроме того, генерируется исключение из-за нулевого значения, и для ячейки устанавливается базовое значение, а представление визуализируется с фоном по умолчанию.

Я что-то делаю не так, я пробовал несколько других вещей, но считаю, что это должен быть правильный способ сделать это.

код c #:

[assembly: ExportRenderer(typeof(CustomViewCell), typeof(CustomViewCellRenderer))]


namespace AIM.iOS {

  class CustomViewCellRenderer : ViewCellRenderer {
    public override UITableViewCell GetCell(Cell item, UITableView tv) {
       UITableViewCell cell;

       try {
          cell = base.GetCell(item, tv);

          var customCell = (CustomViewCell)item;
          var cell = base.GetCell(item, tv);

          var index = tv.IndexPathForCell(cell).Row;

          cell.BackgroundColor = (index % 2 == 0) ? Color.Gray.ToUIColor() :
                                                  Color.White.ToUIColor();
       }catch (Exception ex){
          string message = ex.Message;
          cell = base.GetCell(item, tv);
       }

       return cell  
    }
  }
}

Я расширяю класс ExtendedViewCell из Xamarin-Forms-Labs, который добавляет свойства фона к объекту ViewCell.

namespace AIMUI.Controls {
  public class CustomViewCell : ExtendedViewCell {
    public CustomViewCell() { }
  }
}

Вот Xaml:

<localcontrols:ListView>
  <ListView.ItemTemplate>
    <DataTemplate>
      <localcontrols:CustomViewCell>
        <localcontrols:CustomViewCell.View>
        </localcontrols:CustomViewCell.View>
      </localcontrols:CustomViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</localcontrols:ListView>

Изменить:

Хорошо, поэтому я решил проблему с получением индекса с помощью var index = tv.IndexPathForRowAtPoint(cell.Center).Row;, однако это вызвало другую проблему. Он отлично работает в первый раз, а также при возврате на страницу из дополнительного представления. Однако, когда я покидаю страницу, перехожу к другому виду из masterpage и возвращаюсь, он устанавливает фон всех элементов серым. В настоящее время я создаю новую страницу и затем устанавливаю для нее значение masterpage.details, когда захожу из меню.


person Jared Reeves    schedule 10.10.2014    source источник


Ответы (3)


Это можно сделать с помощью конвертера вместо средства визуализации.

public class StripedBackgroundIndexConverter : 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 index % 2 == 0 ? Color.White : Color.FromRgb(240, 240, 240);
    }

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

Затем назовите свой ListView и передайте его в качестве параметра, используя x: Reference

<ListView x:Name="MyItemsListView" ItemsSource="{Binding MyItems}" SelectedItem="{Binding SelectedMyItem, Mode=TwoWay}">
<ListView.ItemTemplate>
  <DataTemplate>
    <ViewCell>
      <Grid BackgroundColor="{Binding .,Converter={StaticResource StripedBackgroundIndexConverter}, ConverterParameter={x:Reference MyItemsListView}}">

      </Grid>
    </ViewCell>
  </DataTemplate>
</ListView.ItemTemplate>

Of course you can also use the converter in your renderer if you are needing to customize other elements.

person jjthemachine    schedule 23.02.2016

Как вы уже узнали, IndexPathForRowAtPoint вернет индекс строки в источнике данных , даже если строка не отображается, в отличие от IndexPathForCell, который не будет работать правильно, пока ячейка не станет видимой.

Что касается проблемы с навигацией, когда вы помещаете страницы в стек навигации Xamarin.Forms, они не выгружаются и по-прежнему работают незаметно. . Вот почему при однократном переходе назад по стеку навигации и всплывающему вы видите ту же страницу, в точности такую ​​же, что и ранее. от него (если, конечно, у вас нет какой-либо логики в одном из Page обработчиков событий, который будет повторно вызван для выполнения какой-либо другой обработки).

В iOS ячейки ставятся в очередь и удаляются из очереди, когда это необходимо, и могут по-прежнему находиться в памяти, хотя они не видны, ожидая сборки мусора. .

Это звучит очень странно: когда вы уходите со страницы (не в подпредставление), а затем возвращаетесь на эту страницу, это не работает из-за модуля , который вы используете.

В качестве альтернативы, просто для исследования и тестирования, добавьте в свою Модель еще одно поле с увеличивающимся ID, которое вы задаете для модуль, чтобы установить цвет фона строки, чтобы увидеть, можете ли вы изолировать функцию IndexPathForRowAtPoint, которая, возможно, является основной проблемой.

Если вы сможете создать небольшой проект только с этим входом, это будет очень полезно для тех, кто будет помогать дальше?

person Pete    schedule 11.10.2014

После обращения в службу поддержки Xamarin и с их помощью это был результат.

indexPathForPoint не является надежным в зависимости от того, как и когда фактическая ячейка находится на экране. Обычно метод GetCell имеет надежный параметр NSIndexPath, но абстракция Forms не передает его.

Предлагается в качестве улучшения _ 1_

В качестве обходного пути вы можете использовать другой метод index. Однако у меня это не сработало, так как оно не было на 100% надежным. Я не нашел отличного способа реализовать эту функциональность.

В качестве примечания. Я считаю, что это было упущено в процессе разработки кода Xamarin. Не должно быть так сложно просто получить индекс каждой ячейки.

person Jared Reeves    schedule 15.10.2014