2
votes

bit stuck on this. Have a list view and I want to change the theme to match the rest of my app. Been following a few examples of how to change the selected item back color which I have working really well using custom renders, mainly this example https://blog.wislon.io/posts/2017/04/11/xamforms-listview-selected-colour

However no example I've been able to find addresses the fore color of the selected items.

Is that something I would do with custom renders as with the background or am I backing up the wrong tree?

My list view definition is as follows

<ListView.ItemTemplate>
    <DataTemplate>
        <customControls:ExtendedViewCell SelectedBackgroundColor="#5DB8B3">
            <ViewCell.View>
                <StackLayout VerticalOptions="StartAndExpand">
                    <Label Text="{Binding AttributeName}" 
                           FontSize="Small" 
                           FontAttributes="Bold"/>
                    <Label Text="{Binding Description}" 
                           FontSize="Small"/>
                    <Label Text="{Binding CreditorName}" 
                           FontSize="Small"/>
                </StackLayout>
            </ViewCell.View>
        </customControls:ExtendedViewCell>
    </DataTemplate>
</ListView.ItemTemplate>

Appreciate any feedback thank

2
You'll need to use a custom renderer for this.Bejasc
@Bejasc, any chance of more info? Already using custom renders for the back colorHursey
when you say the 'fore color' - what is it exactly that you're trying to change? Text color? Color when not selected? Color when is selected?Bejasc
Yeah, should of been a little more specific on that. The text color of the labels within the view cell stack layout.Hursey
Changing the text color of the labels is pretty simple, I've added an answer for you on how to do that. Apologies if I've misunderstood what you mean.Bejasc

2 Answers

2
votes

You can do this (Without a custom renderer) by adding another property to the object is bound to, and binding TextColor on the label to this new property.

Assuming your bound object looks something like this

public class BoundObject
{
    public string AttributeName { get; set; }
    public string Description { get; set; }
    public string CreditorName { get; set; }

    public int id { get; set; }
    public Color TextColor { get; set; }
}

XAML

Note the ListView control added, with a name property and an ItemSelected event.

<ListView x:Name="myList" ItemSelected="myListSelected">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout VerticalOptions="StartAndExpand">
                    <Label Text="{Binding AttributeName}" 
                        FontSize="Small" 
                        FontAttributes="Bold"
                        TextColor="{Binding TextColor}"
                    />

                    <Label Text="{Binding Description}" 
                        FontSize="Small"
                        TextColor="{Binding TextColor}"
                    />

                    <Label Text="{Binding CreditorName}" 
                        FontSize="Small"
                        TextColor="{Binding TextColor}"
                    />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Code Behind

Most of the magic happens in the code behind. Note that I'm just adding a few items to the list on start here - just for debug purposes. It's important to note that the start color is also given at the time the list needs to be created.

I've also added an ID field to the BoundObject, so we can more easily identify which object we have selected.

    List<BoundObject> listItems = new List<BoundObject>();

    public YourPage()
    {
        InitializeComponent();

        for (int i = 0; i < 10; i++)
        {
            listItems.Add(new BoundObject() { id=i, AttributeName = "Attribute " + i, Description = i + " description", CreditorName = "Creditor: " + i, TextColor = Color.Blue });
        }

        myList.ItemsSource = listItems;
    }


    private void myListSelected(object sender, SelectedItemChangedEventArgs e)
    {
        if (((ListView)sender).SelectedItem == null)
            return;

        //Get the item we have tapped on in the list. Because our ItemsSource is bound to a list of BoundObject, this is possible.
        var selection = (BoundObject)e.SelectedItem;

        //Loop through our List<BoundObject> - if the item is our selected item (checking on ID) - change the color. Else - set it back to blue 
        foreach(var item in listItems)
        {
            if (item.id == selection.id)
                item.TextColor = Color.Red;
            else
                item.TextColor = Color.Blue;
        }

        //ItemsSource must be set to null before it is re-assigned, otherwise it will not re-generate with the updated values. 
        myList.ItemsSource = null;
        myList.ItemsSource = listItems;
    }

The key points to the code-behind are...

  • New property TextColor on your bound object, of type Color
  • Store your BoundObject in a List<BoundObject>
  • When populating your list for the first time, set the TextColor property in your BoundObject
  • In the ItemSelected event for your list, get the current selection, and update the List<BoundObject> setting the colours as your conditions need
  • Set the list ItemSource to null, and re-assign it to the (now updated) List<BoundObject>
0
votes

Can achieve through, a custom renderer , however with this approach the color is not applied when the cell includes a ContextAction.

Using Custom Renderer,

From bugzilla

Using Cross Platform Way (binding), this approach applying the color to all cells(layout) that including a ContextAction

Obviously in Xamarin Forms,

Possible ways to achevie

Stack Overflow discussion