I am facing issue in CollectionView while clicking data in collection view. I'm selecting a middle of data but it goes to a first itself. And I'm facing this issue in 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>
This is the code am using so far. In Android it works fine. I'm facing this issue in iOS only.
My RoomCollectionSelectionChanged Event
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
{
}
}
in ViewModel -> SelectedEvent() List(s) are cleared and again framing List(s) for showing the Blue Underline for Selected item so the List(s) are bouncing while selecting the Item. Kindly Help for reframe the selected Event
CodePudding user response:
Here is minimal code, that scrolls Horizontal CollectionView correctly on both iOS and Android.
Please start from this code. Then add your code to it. If your code still has the symptom, then comment out lines of your code until you find what "breaks" the scrolling. Update code in question with the code you are using, and state which line(s) lead to the symptom.
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;
}
}
}