i have a CollectionView and my custom buttom. I want to make a grid with buttons.When I click on button it change a background color.I want to write in void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e) something AND that the text of label is Name(class field) of SELECTED button.When I click on buttons in collectionview it change color but button is not clickable,it does not see it,if I write image it can read data.Please help me make button clickable
<StackLayout>
<Label x:Name="meow1"></Label>
<CollectionView ItemsSource="{Binding Cars}" x:Name="phonesList"
HeightRequest="90"
ItemsLayout="HorizontalList"
BackgroundColor="Transparent"
SelectionMode="Single"
SelectionChanged="OnCollectionViewSelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame x:Name="frame" CornerRadius="10" BackgroundColor="Black" Padding="0" HeightRequest="90"
WidthRequest="95">
<Grid Padding="0" x:Name="meow">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<controls:CustomButton TintColor="#725762" HeightRequest="90"
WidthRequest="90" CornerRadius="10" HorizontalOptions="Center"
BackgroundColor="White" ImageSource="{Binding ImagePath}" Clicked="Button_OnClicked"/>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
meow1.Text = (e.CurrentSelection.FirstOrDefault() as Car).NameImage;
}
Although not too much understanding the problem , but there is a suggestion about Button
click event in CollectionView
. We will use Command
and CommandParameter
of Button when binding model . And that is the design idea of MVVM.
For example , the Xaml code modeified as follow:
<StackLayout>
<Label x:Name="meow1"
Text="{Binding SelectedCarItem.NameImage}"
FontSize="Large"
VerticalOptions="Start"
HorizontalOptions="CenterAndExpand" />
<CollectionView ItemsSource="{Binding Cars}"
x:Name="phonesList"
HeightRequest="90"
ItemsLayout="HorizontalList"
BackgroundColor="Transparent"
SelectionMode="Single"
SelectedItem="{Binding SelectedCarItem}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame x:Name="frame"
CornerRadius="10"
BackgroundColor="{Binding BgFrameColor}"
Padding="0"
HeightRequest="90"
WidthRequest="95">
<Grid Padding="0"
x:Name="meow">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
HeightRequest="90"
WidthRequest="90"
CornerRadius="10"
HorizontalOptions="Center"
BackgroundColor="{Binding BgButtonColor}"
ImageSource="{Binding ImagePath}"
Command="{Binding TapCommand}"
CommandParameter="{Binding Source={x:Reference frame}, Path=BindingContext}" />
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
Then need to modify the Car model , adding BgColor
,IsSelected
and TapCommand
property:
public class Car : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string NameImage { get; set; }
public string ImagePath { get; set; }
private Color bgFrameColor;
public Color BgFrameColor
{
set
{
if (bgFrameColor != value)
{
bgFrameColor = value;
OnPropertyChanged("BgFrameColor");
}
}
get
{
return bgFrameColor;
}
}
private Color bgButtonColor;
public Color BgButtonColor
{
set
{
if (bgButtonColor != value)
{
bgButtonColor = value;
OnPropertyChanged("BgButtonColor");
}
}
get
{
return bgButtonColor;
}
}
private bool isSelected;
public bool IsSelected
{
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
get
{
return isSelected;
}
}
public ICommand TapCommand
{
get
{
return new Command((e) =>
{
var item = (e as Car);
// logic on item
if (item.isSelected)
{
item.isSelected = false;
item.BgButtonColor = Color.White;
item.BgFrameColor = Color.Black;
PageCollectionView.SelectedCar.Remove(item);
MessagingCenter.Send<object, Car>(this, "Hi", new Car() {NameImage ="Welcome to the car home!" });
}
else
{
item.isSelected = true;
item.BgButtonColor = Color.Blue;
item.BgFrameColor = Color.Yellow;
if (PageCollectionView.SelectedCar.Count == 0)
{
PageCollectionView.SelectedCar.Add(item);
}
else
{
PageCollectionView.SelectedCar[0].isSelected = false;
PageCollectionView.SelectedCar[0].BgButtonColor = Color.White;
PageCollectionView.SelectedCar[0].BgFrameColor = Color.Black;
PageCollectionView.SelectedCar.Remove(PageCollectionView.SelectedCar[0]);
PageCollectionView.SelectedCar.Add(item);
}
MessagingCenter.Send<object, Car>(this, "Hi", item);
}
});
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Add CarModel class to load data :
public class CarModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public List<Car> Cars { get; set; }
//public static Car SelectedCarItem { set; get; }
public CarModel()
{
Cars = new List<Car>();
Cars.Add(new Car() { NameImage = "Lexus", ImagePath = "Lexus.png", BgButtonColor = Color.White, BgFrameColor = Color.Black, IsSelected = false }); ;
Cars.Add(new Car { NameImage = "Audi", ImagePath = "Audi.png", BgButtonColor = Color.White, BgFrameColor = Color.Black, IsSelected = false });
// set default text of label
selectedCarItem = new Car() { NameImage = "Welcome to the car home!" };
}
private Car selectedCarItem;
public Car SelectedCarItem
{
get
{
return selectedCarItem;
}
set
{
if (selectedCarItem != value)
{
selectedCarItem = value;
OnPropertyChanged("SelectedCarItem");
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Now in ContentPage , declare a List<Car>
to store only one item to keep this collection view is single selected. And use MessagingCenter to update carModel.SelectedCarItem
here:
public partial class PageCollectionView : ContentPage
{
public static List<Car> SelectedCar { get; set; }
public PageCollectionView()
{
InitializeComponent();
CarModel carModel = new CarModel();
BindingContext = carModel;
SelectedCar = new List<Car>();
MessagingCenter.Subscribe<object,Car>(this, "Hi", (sender,arg) =>
{
// Do something whenever the "Hi" message is received
carModel.SelectedCarItem = arg;
});
}
}
The effect as follow :
Note: From the sample , you will see that using binding to modify BackgroundColor
and Model Data. Therefore, it's not recommanded to use OnCollectionViewSelectionChanged
to modify text of Lable
.