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

CurrentItem is not binded properly when switching pages programmatically #47

Open
WilkoThomassen opened this issue Nov 4, 2019 · 0 comments

Comments

@WilkoThomassen
Copy link

WilkoThomassen commented Nov 4, 2019

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant