Search code examples
c#xamarinxamarin.formscollectionview

Custom style for Item Selected in CollectionView


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


Solution

  • 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>