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

.NET MAUI集合中Picker恢复后SelectedItem不显示问题求助

Picker在集合渲染中恢复表单后SelectedItem不显示问题

Picker控件在集合内每行渲染一个实例,选择操作可正常执行并触发绑定命令,但表单恢复后,绑定到SelectedItem的Address属性无法在Picker中显示,Picker显示为空项而非对应地址值。

XAML代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:appCtrl="clr-namespace:WS.ORD.Apps.POS.Controls"
             xmlns:appVM="clr-namespace:WS.ORD.Apps.POS.ViewModels"
             xmlns:appModel="clr-namespace:WS.ORD.Apps.POS.Models"
             x:Class="WS.ORD.Apps.POS.Views.PrinterSettingsPage"
             x:Name="page">

    <ContentPage.BindingContext>
        <appVM:PrinterSettingsVM />
    </ContentPage.BindingContext>

    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsVisible="False" />
    </Shell.BackButtonBehavior>

    <ContentPage.Content>
        <VerticalStackLayout BindableLayout.ItemsSource="{Binding Printers}" Spacing="30" Margin="100,50">
            <BindableLayout.ItemTemplate>
                <DataTemplate x:DataType="appModel:PrinterModel">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <Label Grid.Row="0" Grid.Column="0" Text="{Binding Name}" VerticalOptions="Center" />

                        <Picker Grid.Row="0" Grid.Column="1"
                         ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type appVM:PrinterSettingsVM}},Path=Devices}"
                         ItemDisplayBinding="{Binding .}"
                         HorizontalOptions="Fill"
                         VerticalOptions="Center"
                         SelectedItem="{Binding Address, Mode=TwoWay}"
                         Margin="0,0,0,10">
                            <Picker.Behaviors>
                                <toolkit:EventToCommandBehavior EventName="SelectedIndexChanged" Command="{Binding Source={x:Reference page}, Path=BindingContext.PrinterSelectCommand}" CommandParameter="{Binding .}" />
                            </Picker.Behaviors>
                        </Picker>
                    </Grid>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </VerticalStackLayout>
    </ContentPage.Content>
</ContentPage>

页面后台代码

public partial class PrinterSettingsPage : ContentPage
{
    public PrinterSettingsPage()
    {
        InitializeComponent();
    }
}

ViewModel代码

namespace WS.ORD.Apps.POS.ViewModels
{
    internal class PrinterSettingsVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public ICommand PrinterSelectCommand { get; private set; }


        public PrinterSettingsVM()
        {
            this.Devices[0] = "device1";
            this.Devices[1] = "device2";
            this.Devices[2] = "device3";


            this.Printers = new List<PrinterModel>()
            {
                new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device1" },
                new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device2" }
            };
        }


        private string[] _devices = new string[3];
        public string[] Devices
        {
            get { return this._devices; }
            set
            {
                this._devices = value;

                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Devices)));
                }
            }
        }


        private IEnumerable<PrinterModel> _printers;
        public IEnumerable<PrinterModel> Printers
        {
            get { return this._printers; }
            set
            {
                this._printers = value;

                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Printers)));
                }
            }
        }
    }
}

Model代码

namespace WS.ORD.Apps.POS.Models
{
    public class PrinterModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public Guid Id { get; set; }
        public string Name { get; set; }


        private string _address;
        public string Address
        {
            get { return this._address; }
            set
            {
                this._address = value;

                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Address)));
                }
            }
        }
    }
}

解决方案

1. 修正Devices集合初始化方式

当前ViewModel中直接修改数组元素的操作不会触发PropertyChanged事件,因为数组引用未发生变化。改为直接初始化数组:

public PrinterSettingsVM()
{
    // 直接赋值新数组,触发PropertyChanged通知
    Devices = new[] { "device1", "device2", "device3" };

    this.Printers = new List<PrinterModel>()
    {
        new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device1" },
        new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device2" }
    };
}

2. 页面恢复时强制刷新绑定

在页面的OnAppearing方法中,手动触发Printers集合的属性变更通知,确保Picker重新评估SelectedItem:

public partial class PrinterSettingsPage : ContentPage
{
    public PrinterSettingsPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        var vm = BindingContext as PrinterSettingsVM;
        vm?.PropertyChanged?.Invoke(vm, new PropertyChangedEventArgs(nameof(vm.Printers)));
    }
}

3. 替换数组为ObservableCollection(可选)

如果Devices集合需要动态更新,将string[]替换为ObservableCollection<string>,集合元素变化时自动通知UI:

using System.Collections.ObjectModel;

namespace WS.ORD.Apps.POS.ViewModels
{
    internal class PrinterSettingsVM : INotifyPropertyChanged
    {
        // ...其他代码

        private ObservableCollection<string> _devices = new ObservableCollection<string>();
        public ObservableCollection<string> Devices
        {
            get { return _devices; }
            set
            {
                _devices = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Devices)));
            }
        }

        public PrinterSettingsVM()
        {
            Devices.Add("device1");
            Devices.Add("device2");
            Devices.Add("device3");

            this.Printers = new List<PrinterModel>()
            {
                new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device1" },
                new PrinterModel { Id=Guid.NewGuid(), Name="Printer 2", Address="device2" }
            };
        }

        // ...其他代码
    }
}

4. 验证Address数据正确性

在页面OnAppearing中打印Address值,确认ViewModel中的数据是否正确,排除数据丢失的情况:

protected override void OnAppearing()
{
    base.OnAppearing();
    var vm = BindingContext as PrinterSettingsVM;
    if (vm?.Printers != null)
    {
        foreach (var printer in vm.Printers)
        {
            Console.WriteLine($"Printer Address: {printer.Address}");
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:44:55