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

.NET 8中Picker绑定ItemsSource触发范围错误的疑问

.NET 8 Picker切换数据源时的索引越界问题分析

问题场景

以下代码通过绑定实现Picker的数据源切换:

XAML代码

<StackLayout>
    <Picker Grid.Column="2" Grid.Row="2"  MinimumWidthRequest="120"
        ItemsSource="{Binding Units}"
        SelectedItem="{Binding SelectedUnit}"    
        HorizontalOptions="Start"
        ItemDisplayBinding="{Binding UnitName}">
    </Picker>
    <Button Text="Change"
        Clicked="Button_Clicked"/>
</StackLayout>

C#代码

public partial class MainPage : ContentPage
{
    private ObservableCollection<Unit> units;
    public ObservableCollection<Unit> Units
    {
        get { return units; }
        set
        {
            units = value;
            //SelectedUnit = null;
            OnPropertyChanged();
            SelectedUnit = Units.First();
        }
    }

    private Unit selectedUnit;
    public Unit SelectedUnit
    {
        get { return selectedUnit; }
        set
        {
            selectedUnit = value;
            OnPropertyChanged();
        }
    }

    public MainPage()
    {
        BindingContext = this;
        InitializeComponent();

        Units = new ObservableCollection<Unit>()
        {
            new Unit("Meter (m)"),
            new Unit("Decimeter (dm)"),
            new Unit("Centimeter (cm)"),
            new Unit("Milimeter (mm)"),
            new Unit("Foot (ft)"),
            new Unit("Inch (in)")
        };

        SelectedUnit = Units.First();
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        Units = new ObservableCollection<Unit>()
        {
            new Unit("Kilogram (kg)"),
            new Unit("Pound (lbs)"),
            new Unit("Ounce (oz)"),
        };
    }
}

public class Unit
{
    public Unit(string unitName)
    {
        UnitName = unitName;
    }

    public string UnitName { get; }
}

操作步骤:运行程序后选择Picker中后三项任意一项,点击按钮切换数据源集合。

版本差异表现

  • .NET 7.0:Picker正常显示新集合并选中第一项;
  • .NET 8.0:点击按钮后,Units属性调用OnPropertyChanged时触发错误:Value does not fall within the expected range.,取消注释//SelectedUnit = null;可解决问题。

问题本质与官方设计意图

这种行为是**.NET 8的有意设计**,并非Bug。

在.NET 7及更早版本,MAUI的Picker组件会静默处理"SelectedItem不在新ItemsSource中"的情况:自动将SelectedIndex设为-1,后续绑定新的SelectedItem时不会报错。

而.NET 8中,MAUI团队强化了绑定的有效性校验:当ItemsSource更新后,原SelectedItem对应的索引在新集合中不存在时,组件会直接抛出参数越界异常,不再静默修正无效状态。这是为了更早暴露绑定逻辑中的潜在问题,符合.NET平台逐步收紧输入验证的设计趋势。

取消注释SelectedUnit = null;能解决问题的原因是:在触发ItemsSource变更前,先将SelectedItem置空,让Picker的SelectedIndex先回到-1,此时更新ItemsSource后再设置新的SelectedItem,就不会出现索引不匹配的情况,符合组件的绑定状态要求。

最佳实践

在切换Picker的ItemsSource时,建议遵循以下步骤:

  1. 先将SelectedItem设为null;
  2. 更新ItemsSource;
  3. 设置新的SelectedItem。

这样可以避免出现无效绑定状态,适配.NET 8及后续版本的校验逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 17:15:11