You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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>

关键修改说明

  1. 调整BindingContext:将BindingContext从selectedClass改为页面自身(this),让UI绑定能访问到页面类的InstructorsList和SelectedInstructor属性。
  2. 实现INotifyPropertyChanged:给页面类添加属性变更通知机制,确保数据更新后UI能同步刷新。
  3. 修正UI绑定路径:将原绑定到selectedClass属性的控件(如Delete按钮),调整为{Binding SelectedClass.cID}的形式,明确指向页面类中的SelectedClass对象属性。
  4. 移除手动设置SelectedIndex:通过SelectedItem绑定自动同步选中状态,避免索引不匹配的潜在问题。

内容的提问来源于stack exchange,提问作者SqueezeOJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:22:04