Chris Fodor
Chris Fodor

Reputation: 117

Xamarin Forms Changing background color of each ViewCell in ListView

I have reservation times in a listView like 8:00, 9:00 etc. Through JSON I retrieve reservations from remote DB that are already made. So I want to change the background color of each Cell (label) to red that are reserved and rest to green ( free appointments).

This is my xaml code:

    <StackLayout>
    <ListView x:Name="ItemsListView"
            ItemsSource="{Binding Items}"
            VerticalOptions="FillAndExpand"
            HasUnevenRows="true"
            RefreshCommand="{Binding LoadItemsCommand}"
            IsPullToRefreshEnabled="true"
            IsRefreshing="{Binding IsBusy, Mode=OneWay}"
            CachingStrategy="RecycleElement"
            ItemSelected="OnItemSelected">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="10">
                        <Label Text="{Binding Text}" 
                            LineBreakMode="NoWrap" 
                            Style="{DynamicResource ListItemTextStyle}" 
                            FontSize="16" />

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

ListView is populated from a model like:

new Termin { Id = Guid.NewGuid().ToString(), Text = "12:00", Description="" },

So how can I change the color of those cells?

Pseudo code of what I want:

for(int i=0; i< number of items in the listview; i++) {
if(reservations.contains(listview.itemAt(i)) {
//change background color of viewcell (label?) at position i
}
}

Upvotes: 2

Views: 2804

Answers (2)

iman
iman

Reputation: 141

You can use a custom view cell. I've written a custom view cell in my project and used XFGloss(XFGloss is an add-on for Xamarin.Forms projects that adds new properties to the standard XF page and control classes) to make the listView's rows colorful. Your listView will not lose the haptic feedback with XFGloss. The custom viewCell which I used is :

 public class MyViewCell : ViewCell
    {
        private Color BackgroundColor
        {
            get => CellGloss.GetBackgroundColor(this);
            set => CellGloss.SetBackgroundColor(this, value);
        }

        public Color EvenColor { get; set; }
        public Color UnevenColor { get; set; }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            if (!(Parent is ListView listView))
                throw new Exception(
                    $"The Binding Context is not {typeof(ListView)}. This component works only with {typeof(ListView)}.");

            int index;
            if (listView.IsGroupingEnabled)
            {
                index = listView.TemplatedItems.GetGroupAndIndexOfItem(BindingContext).Item2;
            }
            else
            {
                index = listView.TemplatedItems.IndexOf(this);
            }

            if (index != -1)
                BackgroundColor = index % 2 == 0 ? EvenColor : UnevenColor;
        }
    }

and its usage in the xaml file is simple as below line :

<components:MyViewCell EvenColor="White" UnevenColor="#eeeeee">

Upvotes: 0

SushiHangover
SushiHangover

Reputation: 74094

(As Bruno commented)

Add an IsReserved boolean property to your model:

public class Termin
{
    public string Id { get; set; }
    public string Text { get; set; }
    public string Description { get; set; }
    public bool IsReserved { get; set; }
}

IValueConverter that returns Red if IsReserved is true:

public class IsReservedToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((bool)value ? Color.Red : Color.Transparent);
    }

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

Add the namespace of your IValueConverter:

xmlns:local="clr-namespace:SameNameSpace;assembly=SomeAssemblyName"   

Add the IValueConverter to your ContentPage.Resources

<ContentPage.Resources>
    <ResourceDictionary>
        <local:IsReservedToColorConverter x:Key="IsReservedToColor"></local:IsReservedToColorConverter>
    </ResourceDictionary>
</ContentPage.Resources>

Consume the converter in your binding

<Frame BackgroundColor = "{Binding IsReserved, Converter={StaticResource IsReservedToColor}}">

Final XAML Example:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Forms_31_1.ListPage"
    xmlns:local="clr-namespace:Forms_31_1;assembly=Forms_31_1" >
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:IsReservedToColorConverter x:Key="IsReservedToColor"></local:IsReservedToColorConverter>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <ListView x:Name="listView" BackgroundColor="Aqua" SeparatorColor="Red">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Frame BackgroundColor = "{Binding IsReserved, Converter={StaticResource IsReservedToColor}}">
                            <StackLayout Orientation="Vertical">
                                <Label Text="{Binding Text}" />
                                <Label Text="{Binding Description}" />
                            </StackLayout>
                        </Frame>
                </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

Output:

enter image description here

posts.Add(new Termin { Id = Guid.NewGuid().ToString(), Text = "11:00" });
posts.Add(new Termin { Id = Guid.NewGuid().ToString(), Text = "12:00", IsReserved = true });
posts.Add(new Termin { Id = Guid.NewGuid().ToString(), Text = "13:00" });
posts.Add(new Termin { Id = Guid.NewGuid().ToString(), Text = "14:00" });

Upvotes: 3

Related Questions