GBM
GBM

Reputation: 159

How do i change the CurrentItem in a CarouselView?

I am fairly new to MAUI Apps and what i have is a CarouselView bound to a collection of students. Everything is working fine, however I have an issue which appears to be widespread - I have a Next and Previous button which I want to use to navigate from one item in the carousel to the next.

The Previous button works fine, however the Next button doesn't behave as expected. If I have, for example, 3 students in my collection, I cannot smoothly navigate from Student 1 (position 0) to Student 2 (position 1).

I have to click the next button twice and it's only on the 3rd click that it finally moves to student 2. It keeps resetting back to student 1. I monitored the behavior in Debug mode and I can see that the current Item in the preview does indeed change when I debug the NextButton_Clicked method, but as soon as the debug exits the method, the CurrentItem resets back to student 1 (position 0). As I mentioned, my Students collection is working fine and the data is as expected and I do not have any other (visible) triggers that may be overriding the CurrentItem change. For reference, my methods in the code-behind are below:

private void NextButton_Clicked(object sender, EventArgs e)
{
    if (StudentCarousel.ItemsSource is IList<Student> students)
    {
        int studentCount = students.Count;
        int nextPosition = (CurrentPosition + 1) % studentCount;

        Debug.WriteLine($"NextButton_Clicked: Setting Position to {nextPosition}");

        // Update Position before CurrentItem
        CurrentPosition = nextPosition;
        StudentCarousel_CurrentItem = students[nextPosition];

    }
}

private void StudentCarousel_PositionChanged(object sender, PositionChangedEventArgs e)
{
    Debug.WriteLine($"PositionChanged Event: New Position = {e.CurrentPosition}");
}

private void CarouselView_CurrentItemChanged(System.Object sender, Microsoft.Maui.Controls.CurrentItemChangedEventArgs e)
{
    if (e.CurrentItem is Student currentStudent)
    {
        CurrentItem = currentStudent;
    }
}

I also have the code below:

public ObservableCollection<Student> Students { get; set; } = new ObservableCollection<Student>();

private int _currentPosition;

public int CurrentPosition
{
    get => _currentPosition;
    set
    {
        if (_currentPosition != value)
        {
            _currentPosition = value;
            OnPropertyChanged(nameof(CurrentPosition));
            Debug.WriteLine($"CurrentPosition set to: {_currentPosition}");
        }
    }
}

private Student _studentCarousel_CurrentItem;

public Student StudentCarousel_CurrentItem
{
    get => _studentCarousel_CurrentItem;
    set
    {
        if (_studentCarousel_CurrentItem != value)
        {
            _studentCarousel_CurrentItem = value;
            OnPropertyChanged(nameof(StudentCarousel_CurrentItem));
        }
    }
}

Below is the .xaml code:

     <Frame Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" Margin="5" BorderColor="Gray" BackgroundColor="White" HasShadow="True" HeightRequest="250" WidthRequest="300"
HorizontalOptions="Center" VerticalOptions="Center">
         <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center" Padding="10">
             <!-- CarouselView -->
             <RefreshView>
                 <CarouselView x:Name="StudentCarousel" ItemsSource="{Binding Students}" Loop="True"
               HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
               HeightRequest="250" WidthRequest="300" IndicatorView="CarouselIndicator"  IsScrollAnimated="True" CurrentItem="{Binding StudentCarousel_CurrentItem, Mode=TwoWay}" CurrentItemChanged="CarouselView_CurrentItemChanged" Position="{Binding CurrentPosition, Mode=TwoWay}" PositionChanged="StudentCarousel_PositionChanged" >
                     <CarouselView.ItemTemplate>
                         <DataTemplate>
                             <Grid Padding="10" RowSpacing="5" ColumnSpacing="10" HorizontalOptions="Center" VerticalOptions="Center">
                                 <Grid.RowDefinitions>
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                 </Grid.RowDefinitions>
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition Width="Auto" />
                                 </Grid.ColumnDefinitions>

                                 <!-- Image -->
                                 <Image Source="student_icon.png" Grid.Row="0" Grid.Column="0" HeightRequest="40" WidthRequest="40" HorizontalOptions="Center" />

                                 <!-- Label: Student Info -->
                                 <Label Text="Student Info" Grid.Row="1" Grid.Column="0" FontAttributes="Bold" FontSize="Small" HorizontalOptions="Center" VerticalOptions="Center" />

                                 <!-- Label: Full Name -->
                                 <Label Grid.Row="2" Grid.Column="0" HorizontalOptions="Start" VerticalOptions="Center">
                                     <Label.FormattedText>
                                         <FormattedString>
                                             <Span Text="FullName: " FontAttributes="Bold" />
                                             <Span Text="{Binding FullNameWithMiddleName}" />
                                         </FormattedString>
                                     </Label.FormattedText>
                                 </Label>
                             </Grid>
                         </DataTemplate>
                     </CarouselView.ItemTemplate>
                 </CarouselView>
             </RefreshView>
             <!-- Navigation Buttons -->
             <StackLayout Orientation="Horizontal" HorizontalOptions="Center" Margin="0,10,0,0">
                 <Button x:Name="PreviousButton" Text="Previous" Clicked="PreviousButton_Clicked" />
                 <Button x:Name="NextButton" Text="Next" Clicked="NextButton_Clicked" Margin="10,0,0,0" />
             </StackLayout>
         </StackLayout>
     </Frame>

I am completely stuck and not sure where I am going wrong. Any advice is appreciated.

Upvotes: 2

Views: 96

Answers (1)

liyu
liyu

Reputation: 224

Here is my solution.

I remove the currentItem and change it to Student_CurrentItem.

private void CarouselView_CurrentItemChanged(System.Object sender, Microsoft.Maui.Controls.CurrentItemChangedEventArgs e)
{
    if (e.CurrentItem is Student currentStudent)
    {
        Student_CurrentItem = currentStudent;
    }
}

Upvotes: 1

Related Questions