如何在C# MAUI页面显示时填充Picker控件?
解决MAUI中ClassEditPage的Picker控件无法加载数据的问题
问题背景
在C# MAUI的ClassEditPage页面中,尝试在页面显示时填充Instructor_Picker控件。调试输出已确认成功从数据库获取到讲师列表,但Picker始终为空,无任何报错信息。
原代码
ClassEditPage.xaml
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Studio_Sign_In_202307.Pages.ClassEditPage" Title="ClassEditPage"> <StackLayout Padding="20"> <!-- Instructor Picker --> <Label Text="Instructor:" /> <Picker x:Name="Instructor_Picker" Title="Select an Instructor" ItemsSource="{Binding InstructorsList}" SelectedItem="{Binding SelectedInstructor}" SelectedIndexChanged="Instructor_Picker_SelectedIndexChanged"> <Picker.ItemDisplayBinding> <!-- Display the instructor's full name in the picker --> <Binding Path="iFullName" /> </Picker.ItemDisplayBinding> </Picker> <Button Text="Submit" Clicked="OnSubmitClicked" /> <Button Text="Delete" Clicked="OnDeleteClicked" IsVisible="{Binding cID, Converter={StaticResource HasValueConverter}}" /> <Button Text="Cancel" Clicked="OnCancelClicked" /> </StackLayout> </ContentPage>
ClassEditPage.xaml.cs
using Studio_Sign_In_202307.Data; using Studio_Sign_In_202307.Models; using System.Collections.ObjectModel; using System.Diagnostics; namespace Studio_Sign_In_202307.Pages; public partial class ClassEditPage : ContentPage { private readonly Class selectedClass; private readonly bool isNewClass; // Property to hold the collection of instructors public ObservableCollection<Instructor> InstructorsList { get; set; } // Property to hold the selected instructor public Instructor SelectedInstructor { get; set; } public ClassEditPage(Class selectedClass) { InitializeComponent(); // Determine if this is an existing class or a new class isNewClass = selectedClass == null; this.selectedClass = selectedClass ?? new Class(); BindingContext = this.selectedClass; // Create Connection String string connectionString = DatabaseHelper.BuildConnectionString(); // Set the InstructorsList with the data from the database InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString); // Debug instructor list <-- This Displays My Instructors foreach (Instructor instructor in InstructorsList) { Debug.WriteLine($"Instructor ID: {instructor.iID}"); Debug.WriteLine($"Full Name: {instructor.iFullName}"); Debug.WriteLine($"Email: {instructor.iEmail}"); Debug.WriteLine("------------------------"); } // Set the selected instructor for the class (if it has one) if (selectedClass.iID_Link != 0) { SelectedInstructor = InstructorsList.FirstOrDefault(i => i.iID == selectedClass.iID_Link); Instructor_Picker.SelectedIndex = InstructorsList.IndexOf(SelectedInstructor); } } private void Instructor_Picker_SelectedIndexChanged(object sender, EventArgs e) { if (Instructor_Picker.SelectedItem is Instructor selectedInstructor) { SelectedInstructor = selectedInstructor; } } private void OnSubmitClicked(object sender, EventArgs e) { Debug.WriteLine("SUBMIT"); // Submit Logic Here Navigation.PopModalAsync(); } private void OnDeleteClicked(object sender, EventArgs e) { Debug.WriteLine("DELETE"); // Delete Logic Here Navigation.PopModalAsync(); } private void OnCancelClicked(object sender, EventArgs e) { Navigation.PopModalAsync(); } }
问题原因
核心问题是BindingContext设置错误:
- 代码中将
BindingContext设为selectedClass(Class模型对象),但InstructorsList和SelectedInstructor是属于ClassEditPage页面类的属性,并非Class模型的属性,导致Picker的绑定无法找到对应的数据源。
解决方案
修改后的代码
ClassEditPage.xaml.cs(核心修改)
using Studio_Sign_In_202307.Data; using Studio_Sign_In_202307.Models; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; namespace Studio_Sign_In_202307.Pages; public partial class ClassEditPage : ContentPage, INotifyPropertyChanged { private readonly bool isNewClass; // 实现INotifyPropertyChanged接口,确保属性变更能通知UI更新 public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private Class _selectedClass; public Class SelectedClass { get => _selectedClass; set { _selectedClass = value; OnPropertyChanged(); } } private ObservableCollection<Instructor> _instructorsList; public ObservableCollection<Instructor> InstructorsList { get => _instructorsList; set { _instructorsList = value; OnPropertyChanged(); } } private Instructor _selectedInstructor; public Instructor SelectedInstructor { get => _selectedInstructor; set { _selectedInstructor = value; OnPropertyChanged(); // 同步更新课程的讲师关联ID if (SelectedClass != null && value != null) { SelectedClass.iID_Link = value.iID; } } } public ClassEditPage(Class selectedClass) { InitializeComponent(); isNewClass = selectedClass == null; SelectedClass = selectedClass ?? new Class(); // 将BindingContext设置为页面自身,让UI绑定到页面类的属性 BindingContext = this; string connectionString = DatabaseHelper.BuildConnectionString(); InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString); // 调试输出(确认数据已获取) foreach (Instructor instructor in InstructorsList) { Debug.WriteLine($"Instructor ID: {instructor.iID}"); Debug.WriteLine($"Full Name: {instructor.iFullName}"); Debug.WriteLine($"Email: {instructor.iEmail}"); Debug.WriteLine("------------------------"); } // 设置选中的讲师(如果课程已有关联) if (SelectedClass.iID_Link != 0) { SelectedInstructor = InstructorsList.FirstOrDefault(i => i.iID == SelectedClass.iID_Link); } } private void OnSubmitClicked(object sender, EventArgs e) { Debug.WriteLine("SUBMIT"); // 提交逻辑 Navigation.PopModalAsync(); } private void OnDeleteClicked(object sender, EventArgs e) { Debug.WriteLine("DELETE"); // 删除逻辑 Navigation.PopModalAsync(); } private void OnCancelClicked(object sender, EventArgs e) { Navigation.PopModalAsync(); } }
ClassEditPage.xaml(调整绑定路径)
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:Studio_Sign_In_202307.Converters" x:Class="Studio_Sign_In_202307.Pages.ClassEditPage" Title="ClassEditPage"> <ContentPage.Resources> <converters:HasValueConverter x:Key="HasValueConverter" /> </ContentPage.Resources> <StackLayout Padding="20"> <!-- Instructor Picker --> <Label Text="Instructor:" /> <Picker x:Name="Instructor_Picker" Title="Select an Instructor" ItemsSource="{Binding InstructorsList}" SelectedItem="{Binding SelectedInstructor}"> <Picker.ItemDisplayBinding> <Binding Path="iFullName" /> </Picker.ItemDisplayBinding> </Picker> <Button Text="Submit" Clicked="OnSubmitClicked" /> <Button Text="Delete" Clicked="OnDeleteClicked" IsVisible="{Binding SelectedClass.cID, Converter={StaticResource HasValueConverter}}" /> <Button Text="Cancel" Clicked="OnCancelClicked" /> </StackLayout> </ContentPage>
关键修改说明
- 调整BindingContext:将
BindingContext从selectedClass改为页面自身(this),让UI绑定能访问到页面类的InstructorsList和SelectedInstructor属性。 - 实现INotifyPropertyChanged:给页面类添加属性变更通知机制,确保数据更新后UI能同步刷新。
- 修正UI绑定路径:将原绑定到
selectedClass属性的控件(如Delete按钮),调整为{Binding SelectedClass.cID}的形式,明确指向页面类中的SelectedClass对象属性。 - 移除手动设置SelectedIndex:通过
SelectedItem绑定自动同步选中状态,避免索引不匹配的潜在问题。
内容的提问来源于stack exchange,提问作者SqueezeOJ
相关产品推荐
相关产品推荐

