Jared Reeves Jared Reeves - 3 months ago 88
C# Question

Alternating Row Colors in Xamarin Forms ListView IOS

I am trying to write a CustomRenderer that can allow a ListView to have alternating row colors. I have run into an issues and am not sure if it might be a bug or am I just not implementing the renderer correctly:

My expectations for the following code is that each custom view cell should get a color based on it position. However, this is not what is happening, I believe that this this code

tv.IndexPathForCell(cell).Row
should return the cell's index but it is not working as expected. It is currently returning a null value ( which it should if the cell in not part view), but I believe that the cell is part of the table view and thus my issue. If I comment out the
var index = tv.IndexPathForCell(cell).Row;
and then set the background color to a static value the code and view works correctly. In addition an exception is thrown because of the null value and the cell is set to the base and the view renders with a default background.

Am I doing something wrong, I have tried several other things but I believe this should be the correct way to do this.

c# code:

[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
}
}
}


I am extending the ExtendedViewCell class from Xamarin-Forms-Labs which adds background properties to the ViewCell object.

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


Here is the Xaml:

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


Edit:

Ok, so I solved the issue with getting the index by using
var index = tv.IndexPathForRowAtPoint(cell.Center).Row;
, however this has caused another issue. It works perfectly the first time, as well as coming back to the page from a sub view. However, when I leave the page and go to another view from the
masterpage
and come back it sets the background of all items gray. Currently, I am creating a new page and then setting it to the
masterpage.details
, when coming from the menu.

Answer

After contacting Xamarin Support, and with their help this was the result.

indexPathForPoint is not reliable based on how and when the actual cell is on the screen. Typically, the GetCell method has the NSIndexPath parameter which is reliable, but the Forms abstraction does not pass this along.

Suggested as an enhancement HERE

As a workaround, you could use another method for index. However, this did not worked for me, as it was not 100% reliable. I did not find a great way to implement this functionality.

As a side note - I feel that this was over looked in the Xamarin code design process, It should not be this hard to simply get the index of each cell.

Comments