Reputation: 900
Using Binding with an ObservableCollection in .NET MAUI, how do I conditionally set the BackgroundColor property of a GUI element and evaluate the conditions for each item individually?
XAML <Label BackgroundColor="{Binding name.color}"/>
C# if (x) { name.color = Colors.Red; } else { name.color = Colors.Blue; }
or using string data like this:
C# name.color = "#FF0000";
does not work.
C# LabelCommonName.BackgroundColor = Colors.Red;
impossible using a CollectionView.
My actual XAML
I've left out the margins, paddings, grid definitions and other irrelevant styling.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:projectName"
x:Class="projectName.CalendarPage"
Title="CalendarPage">
<Grid>
<ScrollView>
<RefreshView x:Name="CalendarRefresh"
Refreshing="RefreshCalendar">
<CollectionView x:Name="CalendarView">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:Calendar">
<Frame>
<Grid>
<!-- Trying to evaluate this BackgroundColor for each item in the CollectionView individually, so not the same value for all items: -->
<Label BackgroundColor="{Binding
if (name.color=1) {
Colors.Red
} else if (name.color=2) {
Colors.Blue
} else {
Colors.Green
}
}"
x:Name="LabelCommonName"
Text="{Binding name.common}"/>
<Label Text="{Binding name.scientific}"/>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</ScrollView>
</Grid>
</ContentPage>
My code behind
Using an ObservableCollection to add more items when scrolling down.
public partial class CalendarPage : ContentPage
{
private ActivityIndicator activityIndicator = new ActivityIndicator() { IsRunning = false };
private ObservableCollection<Calendar> calendars = new ObservableCollection<Calendar>();
private string url = "[censored]";
private int start = 0;
private int limit = 10;
public CalendarPage()
{
InitializeComponent();
LoadCalendar();
}
private void RefreshCalendar(object sender, EventArgs e)
{
LoadCalendar();
CalendarRefresh.IsRefreshing = false;
}
private void ScrollCalendar(object sender, ItemsViewScrolledEventArgs e)
{
if (e.LastVisibleItemIndex > (start - limit))
{
LoadCalendar();
}
}
private async void LoadCalendar()
{
if (activityIndicator.IsRunning == true)
{
return;
}
else
{
activityIndicator.IsRunning = true;
var http = new HttpClient();
var items = await http.GetFromJsonAsync<List<Calendar>>(url + start + limit);
foreach (var item in items)
{
calendars.Add(item);
}
CalendarView.ItemsSource = calendars;
activityIndicator.IsRunning = false;
start += limit;
}
}
}
Calendar class
Items are collected through an API externally so there's an item template.
namespace projectName;
public class Calendar
{
public int item_id { get; set; }
public int status { get; set; }
public Name name { get; set; }
}
public class Name
{
public string common { get; set; }
public string scientific { get; set; }
public string color { get; set; }
}
Upvotes: 1
Views: 1903
Reputation: 8220
You may use a Binding value converters.
You could define a ColorChangedConverter which inherit IValueConverter:
public class ColorChangedConverter : IValueConverter
{
public ColorChangedConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((int)value == 1)
{
return Colors.Red;
}
else if ((int)value == 2)
{
return Colors.Blue;
}
else
{
return Colors.Green;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And in xaml consume Converters:
<ContentPage.Resources>
<local:ColorChangedConverter x:Key="colorChangedConverter" />
</ContentPage.Resources>
<Grid>
<ScrollView>
<RefreshView x:Name="CalendarRefresh" >
<CollectionView x:Name="CalendarView">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:Calendar">
<Frame x:Name="myframe">
<StackLayout>
<Label x:Name="LabelCommonName"
Text="{Binding name.common}" BackgroundColor="{Binding name.color,Converter={StaticResource colorChangedConverter}}">
</Label>
<Label Text="{Binding name.scientific}"
TextColor="{Binding name.color}"/>
<Label x:Name="mylabel" Text="{Binding item_id}"/>
</StackLayout>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</ScrollView>
</Grid>
In code behind, I add some test code:
private ObservableCollection<Calendar> calendars = new ObservableCollection<Calendar>();
public MainPage()
{
InitializeComponent();
LoadCalendar();
}
private async void LoadCalendar()
{
calendars.Add(new Calendar
{
item_id = 1,
status = 1,
name = new Name
{
common = "common1",
scientific = "scientific1",
color = 1
}
});
calendars.Add(new Calendar
{
item_id = 2,
status = 2,
name = new Name
{
common = "common2",
scientific = "scientific2",
color = 2
}
});
calendars.Add(new Calendar
{
item_id = 3,
status = 3,
name = new Name
{
common = "common3",
scientific = "scientific3",
color = 3
}
});
CalendarView.ItemsSource = calendars;
}
The following image shows the result:
Hope it works.
Upvotes: 3