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>
The binding context inside your
CarouselViewis of typeStudentCourses, while your previous statement on ContentPage levelx:DataType="vm:StudentPageModel"(cascading to all it children includingCarouselView) is conflicting with that fact, so in this case you have to specify that yourCarouselViewis expecting aStudentCoursesas a binding context type: