Reputation: 540
I'm using a collectionView and I want to use a custom style for the selected item. I already try to bind the style with a property but I still can't change only the style of the selected item.
Did anyone already did this ? Thanks
Here is the code :
ListTypePOI = new CollectionView()
{
SelectionMode = SelectionMode.Single,
ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Horizontal),
HeightRequest = 60,
BackgroundColor = (Color)Application.Current.Resources["LightBackgroundColor"],
VerticalScrollBarVisibility = ScrollBarVisibility.Never,
VerticalOptions = LayoutOptions.Start,
};
ListTypePOI.SetBinding(SelectableItemsView.SelectedItemProperty, "SelectedTypePOI", BindingMode.TwoWay);
ListTypePOI.SetBinding(ItemsView.ItemsSourceProperty, "TypesPOI");
ListTypePOI.ItemTemplate = new DataTemplate(() =>
{
Frame frame = new Frame()
{
WidthRequest = 90,
Margin = new Thickness(5, 5, 5, 5),
VerticalOptions = LayoutOptions.Start,
Padding = 5,
};
var tap = new TapGestureRecognizer();
tap.Tapped += Tap_Tapped;
frame.GestureRecognizers.Add(tap);
if (compteur < TypesPOI.Count)
{
StackLayout stackLayout = new StackLayout() { Orientation = StackOrientation.Horizontal, Padding = new Thickness(5, 5, 5, 5) };
Label lbl = new Label
{
Style = (Xamarin.Forms.Style)Application.Current.Resources["MainLabelStyle"],
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = this.FontSizeXXSmall,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
};
lbl.SetBinding(Label.TextProperty, "Libelle");
var type = TypesPOI.ElementAt(compteur);
Image image = new Image
{
Aspect = Aspect.AspectFit,
VerticalOptions = LayoutOptions.Center
};
image.Source = ImageSource.FromStream(() => new MemoryStream(type.Icone));
stackLayout.Children.Add(image);
stackLayout.Children.Add(lbl);
frame.Content = stackLayout;
compteur++;
}
Binding b = new Binding("StyleFrameClicked", BindingMode.OneWay, source: this);
frame.SetBinding(Frame.StyleProperty,b);
return frame;
});
ListTypePOI.Style = (Xamarin.Forms.Style)Application.Current.Resources["SelectItemTypePOI"];
StyleFrameClicked = (Xamarin.Forms.Style)Application.Current.Resources["ListViewCellFrameStyle"];
FrameTypePoi.Content = ListTypePOI;
private void Tap_Tapped(object sender, EventArgs e)
{
StyleFrameClicked = (Xamarin.Forms.Style)Application.Current.Resources["ListViewCellFrameStyle"];
Frame frame = (Frame)sender;
frame.Style = (Xamarin.Forms.Style)Application.Current.Resources["ListViewCellClickedFrameStyle"];
}
I used the GestureRecognizer for the detection for my frame click
Upvotes: 0
Views: 2515
Reputation: 540
So, after a lot of search i found a good solution,
I used the VisualStateManager
.
Frame lastElementSelected;
private void Tap_Tapped(object sender, EventArgs e)
{
if (lastElementSelected != null)
VisualStateManager.GoToState(lastElementSelected, "UnSelected");
VisualStateManager.GoToState((Frame)sender, "Selected");
lastElementSelected = (Frame)sender;
}
In app.xaml :
<Style TargetType="Frame">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource GrayBackgroundColor}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="UnSelected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
Upvotes: 2
Reputation: 10978
Due to some definition I do not have, I make a sample code to perform how to change the style at runtime of collectionView. I make the style in xaml and use the easy layout in xaml as well. You could use stacklayout or frame, it is the same.
Xaml:
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="StackLayout">
<Setter Property="BackgroundColor" Value="Gray" />
</Style>
<Style x:Key="AccentStyle" TargetType="StackLayout">
<Setter Property="BackgroundColor" Value="Accent" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<CollectionView ItemsSource="{Binding people}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
x:Name="stackLayout"
Orientation="Horizontal"
Style="{StaticResource baseStyle}">
<Label Text="{Binding Name}" />
<Label Text="{Binding Age}" />
<Label Text="{Binding Country}" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage.Content>
Code:
public partial class Page1 : ContentPage
{
public ObservableCollection<Person> people { get; set; }
public Page1()
{
InitializeComponent();
people = new ObservableCollection<Person>()
{
new Person(){ Name="A", Age=15, Country="CountryA"},
new Person(){ Name="B", Age=16, Country="CountryB"},
new Person(){ Name="C", Age=17, Country="CountryC"},
new Person(){ Name="D", Age=18, Country="CountryD"}
};
this.BindingContext = this;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var s = (StackLayout)sender;
s.Style = (Style)Resources["AccentStyle"];
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Country { get; set; }
}
Upvotes: 3