SJaka
SJaka

Reputation: 840

Error XFC0045 - How to bind a CarouselView to ObservableCollection in Maui?

I'm trying to bind an ObservableCollection to a <CarouselView>. Inside the CarouselView I've a <Label> and I'm trying to bind it to a public property inside the ObservableCollection. However, on compile, I'm getting an error:

Error XFC0045 : Binding: Property "CoursesName" not found on StudentPageModel

I've verified that API call in the StudentPageModel is working as expected on page load (by commenting out the CarouselView) and correct data is available for binding.

StudentPageModel.cs

public partial class StudentPageModel() : ObservableObject
{

    [ObservableProperty]
    private string _studentId = string.Empty;
    
    [ObservableProperty]
    private StudentModel? _student;

    public ObservableCollection<StudentCourses>? CourseCollection { get; set; }
    

    public async Task OnAppearing()
    {
        Student = await GetStudent("A100");

        // Verified that data is getting populated in both Students and CourseCollection
        if (Student is { StudentCourses: not null })
        {
            CourseCollection = new ObservableCollection<StudentCourses>(Students.StudentCourses);
        }        
    }
}

StudentModel.cs

public class StudentModel : ObservableObject
{
    public string? StudentId { get; set; }

    public string? Name { get; set; }

    public string? Major {get; set;}

    public double GPA {get; set;}

    public ObservableCollection<StudentCourses>? CoursesTaken { get; set; }
    
}

StudentCourses.cs

public class StudentCourses
{
    public string? Id { get; set; }
    
    public string? CoursesName { get; set; }

    public string? CoursesGrade { get; set; }

    public string? CoursesCredit { get; set; }

    public string? CoursesSemester { get; set; }
}

StudentAPI Call

public class StudentLoader() : IStudentManager
{    
    public async Task<StudentModel> GetStudent(string studentId)
    {
        try
        {
            var response = await studentAPI.GetStudentAsync(taskId);

            List<StudentCourses>? courses = response.Courses?.Select(course => new StudentCourses
            {
                Id = course.Id,
                CoursesName = course.CoursesName,
                CoursesGrade = course.CoursesGrade,
                CoursesCredit = course.CoursesCredit,
                CoursesSemester = course.CoursesSemester
            }).ToList();
            
            StudentModel student = new()
            {
                StudentId = response.StudentId,
                Name = response.Name,
                Major = response.Major,
                GPA = response.GPA
            };

            if (courses != null)
            {
                student.Courses = new ObservableCollection<StudentCourses>(courses);
            }

            return student;
        }
    }
}

StudentPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:StudentManager.ViewModels"
             x:Class="StudentManager.Pages.StudentPage"
             xmlns:controls="clr-namespace:StudentManager.Controls"
             x:DataType="vm:StudentPageModel">

    <ContentPage.Content>
        <VerticalStackLayout>
            <Label Text="{Binding StudentId}"
                   Margin="10,8,10,8"
                   />
            <Label Text="{Binding Name}"
                   Margin="10,8,10,8"
                   />
            <CarouselView ItemsSource="{Binding CourseCollection}"
                          CurrentItem="{Binding SelectedCourse}">
                <CarouselView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout>
                            <Label Text="{Binding CoursesName}"
                                   FontAttributes="Bold"
                                   FontSize="18"
                                   HorizontalOptions="Center"
                                   VerticalOptions="Center" />
                                    
                        </StackLayout>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
            </CarouselView>
        </VerticalStackLayout>
    </ContentPage.Content>
</ContentPage>

Upvotes: 0

Views: 77

Answers (1)

Cfun
Cfun

Reputation: 9721

The binding context inside your CarouselView is of type StudentCourses, while your previous statement on ContentPage level x:DataType="vm:StudentPageModel" (cascading to all it children including CarouselView) is conflicting with that fact, so in this case you have to specify that your CarouselView is expecting a StudentCourses as a binding context type:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:StudentManager.ViewModels"
             x:Class="StudentManager.Pages.StudentPage"
             xmlns:controls="clr-namespace:StudentManager.Controls"
             x:DataType="vm:StudentPageModel">
...
            <CarouselView x:DataType="vm:StudentCourses"
                          ItemsSource="{Binding CourseCollection}"
                          CurrentItem="{Binding SelectedCourse}">
...

Upvotes: 1

Related Questions