CollectionView 中所选项目的自定义样式

Custom style for Item Selected in CollectionView

我正在使用 collectionView,我想为所选项目使用自定义样式。 我已经尝试将样式与 属性 绑定,但我仍然无法仅更改所选项目的样式。

有人做过吗?谢谢

这是代码:

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"];
}

我使用 GestureRecognizer 来检测我的框架点击

由于一些我没有的定义,我做了一个示例代码来执行如何在运行时更改collectionView的样式。我在 xaml 中制作样式并在 xaml 中使用简单的布局。你可以用stacklayout或者frame,都是一样的。

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>

代码:

 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; }
}

所以,经过大量搜索,我找到了一个很好的解决方案, 我用的是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;
        }

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