选择项目时出现水平集合视图错误

Horizontal Collection View Error While Selecting Items

我在 CollectionView 中单击集合视图中的数据时遇到问题。 我正在选择数据的中间部分,但它本身是第一个。我在 iOS.

中遇到了这个问题
 <CollectionView 
                x:Name="rooms_List"
                IsEnabled="True"
                SelectedItem="{Binding SelectedRoom}"
                SelectionChangedCommand="{Binding Source={x:Reference ThePage}, Path= BindingContext.RoomChanged}"
                ItemsLayout = "HorizontalList"
                SelectionChanged="RoomCollectionSelectionChanged"
                BackgroundColor = "white"
                HeightRequest="50"
                SelectionMode="Single"
                HorizontalScrollBarVisibility="Never"
                ItemsSource="{Binding RoomList}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <StackLayout Orientation="Horizontal" Margin="0,0,0,15">
                                <StackLayout VerticalOptions="Start" Orientation="Vertical">
                                    <Label  Text ="{Binding RoomName}"  Padding="20,10,20,0" />
                                    <BoxView x:Name="line" HeightRequest="3" IsVisible="{Binding IsSelected}" BackgroundColor="#1484B8" WidthRequest="5" Margin="18,0,15,0" />
                                </StackLayout>
                            </StackLayout>
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>

这是目前使用的代码。在 Android 它工作正常。我仅在 iOS 中遇到此问题。

我的 RoomCollectionSelectionChanged 事件

private void RoomCollectionSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.CurrentSelection.Count == 0)
            {
                room_image.IsVisible = true;
            }
            else
            {
                var selectedItem = e.CurrentSelection.FirstOrDefault() as Room;
                selectedRoom = selectedItem.RoomName;
                if (selectedRoom == "All")
                {
                    room_image.IsVisible = false;
                }
                else if (e.PreviousSelection.Count == 1)
                {
                    var previousItem = (e.PreviousSelection.FirstOrDefault() as Room)?.RoomName;
                    if (previousItem != "")
                    {
                        room_image.IsVisible = true;
                        room_image.Source = selectedItem.RoomImage;
                    }
                }
                else
                { 
                    room_image.IsVisible = true;
                    room_image.Source = selectedItem.RoomImage;
                }
            }
        }

ViewModel - SelectedRoomEvent

 private void SelectedRoomEvent()
        {
            if (SelectedRoom != null)
            {
                string RoomName = SelectedRoom.RoomName;
                if (RoomName.Equals("All"))
                {
                    GetDeviceAndRoomData();
                }
                else
                {
                    int RoomId = SelectedRoom.RoomId;
                    RoomList.Clear();
                    var rooms = db.GetRoomAsync().Result.ToList();
                    roomList.Add(new Room
                    {
                        Id = 0,
                        RoomId = 0,
                        RoomName = "All",
                        RoomImage = "none",
                        IsSelected = false
                    });
                    foreach (var room in rooms)
                    {
                        Room r = new Room();
                        r.Id = room.Id;
                        r.RoomId = room.RoomId;
                        r.RoomName = room.RoomName;
                        r.RoomImage = room.RoomImage;
                        r.IsSelected = (r.RoomName == RoomName) ? true : false;
                        RoomList.Add(r);
                    }
                }
            }
            else
            {

            }
        }

更新

列表在选择项目时弹回到开头,因为在 ViewModel -> SelectedEvent() 中,列表被清除并再次创建,以显示所选项目的蓝色下划线。如何在不清除列表的情况下执行此操作?

这是最少的代码,可以在 iOS 和 Android 上正确滚动 Horizo​​ntal CollectionView。

请从这段代码开始。然后将您的代码添加到其中。如果您的代码仍然有此症状,请注释掉您的代码行,直到您找到“中断”滚动的原因。使用您正在使用的代码更新有问题的代码,并说明导致该症状的行。

github repo here.

MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="true"
             x:Class="XFIOSHorizCollViewScrollBug.MainPage">

    <StackLayout>
        <!--SelectionChangedCommand="{Binding Source={x:Reference ThePage}, Path= BindingContext.RoomChanged}"-->
        <CollectionView 
                    x:Name="rooms_List" ItemsLayout = "HorizontalList" ItemsSource="{Binding RoomList}"
                    SelectionChanged="RoomCollectionSelectionChanged" HeightRequest="50"
                    SelectionMode="Single" HorizontalScrollBarVisibility="Never" >
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <StackLayout Orientation="Horizontal" Margin="0,0,0,15">
                            <StackLayout VerticalOptions="Start" Orientation="Vertical">
                                <Label  Text ="{Binding RoomName}"  Padding="20,10,20,0" />
                                <BoxView x:Name="line" HeightRequest="3" IsVisible="{Binding IsSelected}" BackgroundColor="#1484B8" WidthRequest="5" Margin="18,0,15,0" />
                            </StackLayout>
                        </StackLayout>
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

</ContentPage>

MainPage.xaml.cs:

using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;

namespace XFIOSHorizCollViewScrollBug
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            InitRoomList();
            BindingContext = this;
        }

        public ObservableCollection<Room> RoomList { get; set; }

        private Room _previousSelection;

        private void RoomCollectionSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selectedItem = e.CurrentSelection.FirstOrDefault() as Room;
            SelectRoom(selectedItem);
        }

        private void SelectRoom(Room room)
        {
            if (room != null) {
                if (_previousSelection != null)
                    _previousSelection.IsSelected = false;

                room.IsSelected = true;
                rooms_List.ScrollTo(room, position: ScrollToPosition.Center, animate: false);

                _previousSelection = room;
            }
        }

        string[] roomNames = new string[] {
            "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"
        };

        private void InitRoomList()
        {
            var rooms = new ObservableCollection<Room>();
            foreach (var name in roomNames) {
                rooms.Add(new Room(name));
            }

            var room = rooms[0];
            room.IsSelected = true;
            _previousSelection = room;

            RoomList = rooms;
        }
    }
}

Room.cs:

namespace XFIOSHorizCollViewScrollBug
{
    public class Room : Xamarin.Forms.BindableObject
    {
        public string RoomName { get; set; }

        public bool IsSelected {
            get => _isSelected;
            set {
                _isSelected = value;
                OnPropertyChanged();
            }
        }
        private bool _isSelected;

        public Room(string name, bool isSelected = false)
        {
            RoomName = name;
            IsSelected = isSelected;
        }
    }
}