I have a question regarding a listview in Xamarin.Forms binded my listview succesfully with some items but i want to change the background color of the selected cell how do i do this in Xamarin.Forms
I make use of
var cell = DataTemplate(typeof(ImageCell));
ListView listView = new ListView
{
SeparatorColor = Color.Green,
ItemsSource = ListlvData,
ItemTemplate = cell, // Set the ImageCell to the item templatefor the listview
};
Edit 2:
Sometime if I have run into strange issues where my ViewCell
's BackgroundColor
never changes back to the original color so I have started doing this to change the color instead:
cell.Tapped += async (sender, args) => {
cell.View.BackgroundColor = Color.Red;
#pragma warning disable 4014 //These pragma's are only needed if your Tapped is being assigned an async anonymous function and muffles the compiler warning that you did not await Task.Run() which you do not want to fire and forget it
Task.Run(async () => { //Change the background color back after a small delay, no matter what happens
await Task.Delay(300); //Or how ever long to wait
Device.BeginInvokeOnMainThread(() => cell.View.BackgroundColor = Color.Default); //Turn it back to the default color after your event code is done
});
#pragma warning restore 4014
await OnListViewTextCellTapped(cell); //Run your actual `Tapped` event code
};
Edit:
To add the below code to a ListView.DataTemplate
, you would want to do something like this:
ListView listView = new ListView {
SeparatorColor = Color.Green,
ItemsSource = ListlvData
};
listView.ItemTemplate = new DataTemplate(() => {
ViewCell cell = new ViewCell();
cell.Tapped += (sender, args) => {
cell.View.BackgroundColor = Color.Red;
OnListViewTextCellTapped(cell); //Run your actual `Tapped` event code
cell.View.BackgroundColor = Color.Default; //Turn it back to the default color after your event code is done
};
cell.View = new Image();
return cell;
});
To change the background color on Tapped
you will need to use a ViewCell
and an Image
control within that since ImageCell
does not support BackgroundColor
s by default.
I put a StackLayout
within the ViewCell
but then on the Tapped
event, I change the ViewCell.View
's BackgroundColor
, like so:
ViewCell cell = new ViewCell();
cell.Tapped += (sender, args) => {
cell.View.BackgroundColor = Color.Red;
OnListViewTextCellTapped(cell); //Run your actual `Tapped` event code
cell.View.BackgroundColor = Color.Default; //Turn it back to the default color after your event code is done
};
I know this has been answered quite some time ago, but figured I would add a bit more information here for anybody that may stumble across this question looking for a more MVVM friendly way of doing this. I ended up with the following, which somebody would hopefully find useful if they are so inclined.
You will need a value converter such as the following:
public class UseColorIfConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? parameter : Color.Transparent;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The converter simply returns the appropriate Color
if the provided parameter evaluates to true. I have also registered this converter as a static resource in my App.xaml (which had to be manually created) i.e:
<?xml version="1.0" encoding="utf-8" ?>
<forms:FormsApplication xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:forms="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"
x:Class="Path.To.Application.App"
xmlns:converters="clr-namespace:Path.To.Converters.Namespace;assembly=Converter.Assembly">
<Application.Resources>
<converters:UseColorIfConverter x:Key="UseColorIf"></converters:UseColorIfConverter>
</Application.Resources>
</forms:FormsApplication>
Please note that I am using Caliburn Micro, however the same would work for the default Xamarin.Forms.Application class as well.
The usage of the converter and potential bindings would then be the following:
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView BackgroundColor="{Binding Path=Selected, Converter={StaticResource UseColorIf}, ConverterParameter={x:StaticResource ListSelectionColor}}" ...>
<!--Display-->
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This then allows you to bind against a property in each view model which indicates whether it is selected or not. This property has to be kept in sync but is easily enough done by subscribing to the property changed events for example:
public class MenuViewModel : Screen
{
public BindableCollection<SectionViewModel> Items { get; }
public MenuViewModel(IEnumerable<SectionViewModel> sections)
{
Items = new BindableCollection<SectionViewModel>(sections);
PropertyChanged += OnPropertyChanged;
}
private SectionViewModel _selectedItem;
public SectionViewModel SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem == value)
return;
_selectedItem = value;
NotifyOfPropertyChange(nameof(SelectedItem));
}
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (propertyChangedEventArgs.PropertyName == nameof(SelectedItem))
{
foreach (var item in Items)
{
item.Selected = item == SelectedItem;
}
}
}
}
There is also one niggling thing remaining after doing this and that is the default renderer used on each platform. I haven't checked Android, but at least on IOS you will still get a gray border so the following just removes it:
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ViewCell), typeof(CustomListViewCellRenderer))]
namespace My.Awesome.Ios.Client.Renderers
{
class CustomListViewCellRenderer : ViewCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var cell = base.GetCell(item, reusableCell, tv);
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
return cell;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With