xamlxamarin.formscollectionviewvisualstatemanager

VisualStateManager not work with SelectionChanged in a CollectionView on Xamarin Forms


When I add a SelectionChanged function in the collection view, VisualStateManager does not work.

<ContentPage.Resources>
    <Style TargetType="StackLayout">
        <Setter Property="VisualStateManager.VisualStateGroups">
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="LightSkyBlue"/>
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </Setter>
    </Style>
</ContentPage.Resources>

When I add this code in CollectionView: SelectionChanged="OnCollectionViewSelectionChanged", the VisualStateManager stop to work. Does anyone know why?


Solution

  • The issue caused that the SelectionChanged could not get the selected element type like StackLayout or Label. You could use TapGestureRecognizer instead.

    Xaml:

       <ContentPage.Resources>
        <Style TargetType="StackLayout">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup>
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="Accent" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="UnSelected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="Blue" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout
            Padding="10"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand">
            <CollectionView
                x:Name="MenuCollection"
                ItemsSource="{Binding Infos}"
                SelectionChanged="MenuCollection_OnSelectionChanged"
                SelectionMode="Single"
                VerticalScrollBarVisibility="Always">
    
                <CollectionView.ItemsLayout>
                    <GridItemsLayout
                        HorizontalItemSpacing="15"
                        Orientation="Vertical"
                        Span="2"
                        VerticalItemSpacing="15" />
                </CollectionView.ItemsLayout>
    
                <CollectionView.ItemTemplate>
                    <DataTemplate>
    
                        <StackLayout BackgroundColor="Blue">
                            <Label Text="{Binding Title}" />
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
                            </StackLayout.GestureRecognizers>
                        </StackLayout>
    
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </StackLayout>
    </ContentPage.Content>
    

    Code behind:

     public partial class Page4 : ContentPage
    {
        public ObservableCollection<Info> Infos { get; set; }
        public Page4()
        {
            InitializeComponent();
            Infos = new ObservableCollection<Info>
        {
            new Info(){ Title="A"},
            new Info(){ Title="B"},
            new Info(){ Title="B"},
            new Info(){ Title="C"},
            new Info(){ Title="D"}
        };
    
            this.BindingContext = this;
        }
        StackLayout lastElementSelected;
        private void MenuCollection_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {      
    
         
    
        }
    
        private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {
    
            if (lastElementSelected != null)
                VisualStateManager.GoToState(lastElementSelected, "UnSelected");
    
            VisualStateManager.GoToState((StackLayout)sender, "Selected");
    
            lastElementSelected = (StackLayout)sender;
        }
    }
    public class Info
    {
        public string Title { get; set; }
    }
    

    Screenshot:

    enter image description here