.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
相关产品推荐
相关产品推荐

