Skip to content
This repository was archived by the owner on Jun 19, 2024. It is now read-only.
This repository was archived by the owner on Jun 19, 2024. It is now read-only.

CurrentItem is not binded properly when switching pages programmatically #47

Description

@WilkoThomassen

I have a setup where the carouselview has a binded property "CurrentItem". When we set currentitem to the next page programatically the binded property will be set 4 times. 3 times the proper item, but 1 time it is the wrong (previous) object.
This has a negative effect on components that respond to the current page index like page button states or a stepsindicator.

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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="TestCarousel.MainPage">
    <StackLayout>
        <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <CarouselView 
                x:Name="testCarousel"
                ItemsSource="{Binding TestCollection}"
                CurrentItem="{Binding CurrentTestModel}">
                <CarouselView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout>
                            <Label Text="Title"/>
                            <Label Text="{Binding Title}"/>
                            <Label Text="Description"/>
                            <Label Text="{Binding Description}"/>
                        </StackLayout>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
            </CarouselView>
            <Button Text="Previous" Command="{Binding PreviousPageCommand}" />
            <Button Text="Next" Command="{Binding NextPageCommand}" />
        </StackLayout>
    </StackLayout>
</ContentPage>

codebehind:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace TestCarousel
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage, INotifyPropertyChanged
    {
        public MainPage()
        {
            InitializeComponent();

            this.Appearing += MainPage_Appearing;
            this.BindingContext = this;

            this.testCarousel.Scrolled += TestCarousel_Scrolled;
            this.testCarousel.CurrentItemChanged += TestCarousel_CurrentItemChanged;
        }

        private void MainPage_Appearing(object sender, EventArgs e)
        {
            this.TestCollection = new ObservableCollection<TestModel>()
            {
                new TestModel() { Title = "Title 1", Description = "Description 1"},
                new TestModel() { Title = "Title 2", Description = "Description 2"},
                new TestModel() { Title = "Title 3", Description = "Description 3"},
                new TestModel() { Title = "Title 4", Description = "Description 4"},
                new TestModel() { Title = "Title 5", Description = "Description 5"},
            };

            this.CurrentTestModel = TestCollection[0];
        }

        private ObservableCollection<TestModel> testCollection;
        public ObservableCollection<TestModel> TestCollection 
        {
            get
            {
                return testCollection;
            }
            set
            {
                testCollection = value;
                RaisePropertyChanged();
            }
        }

        private int pageIndex = 0;
        public int PageIndex
        {
            get
            {
                return pageIndex;
            }
            set
            {
                pageIndex = value;
            }
        }

        private TestModel currentTestModel;
        public TestModel CurrentTestModel 
        {
            get
            {
                return currentTestModel;
            }
            set
            {
                currentTestModel = value;
                Debug.WriteLine($"CurrentPage changed to {TestCollection.IndexOf(value)}");
                RaisePropertyChanged();
            }
        }


        public Command NextPageCommand
        {
            get
            {
                return new Command(() => {
                    PageIndex++;
                    CurrentTestModel = TestCollection[PageIndex];
                });
            }
        }

        public Command PreviousPageCommand
        {
            get
            {
                return new Command(() => {
                    PageIndex--;
                    CurrentTestModel = TestCollection[PageIndex];
                });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises the property changed.
        /// </summary>
        /// <param name="propertyName">(Optional) Property name.</param>
        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class TestModel
    {
        public string Title { get; set; }
        public string Description { get; set; }
    }
}

Steps to reproduce:

Unzip the sample project in the zipfile and run it.

CarouselView - Bugreport.zip

Tab the next button and you will see the following debugging line:

image

Results in the following debugging output:

image

System info:

Xamarin.Forms: 4.3.0.947036
Tested on: Android 8, Android 9

Update:

I have tested the same code in iOS (build against xcode 11) and it results in the same kind of problems.

When you tap on the next button, carousel does not animate to the next page. In XF 4.3.0.819712-pre2 it works perfectly fine but in the latest stable (4.3.0.947036) it is not working

Tested on iPhone 6 - iOS 12.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions