.net MAUI Picker SelectedIndex 不会导致项目显示

问题描述 投票:0回答:1

我无法使 SelectedIndex 的预期行为起作用。该项目未显示。选择选择器时,itempOrce,itemDisplayBinding和SelectedItem正在工作,但是当首先显示视图时,选择器未显示列表中的对象。

我创建了一个测试.Maui APP如下;

View MainPage.xml:

<?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:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:models="clr-namespace:MauiPicker;assembly=MauiPicker" xmlns:viewModels="clr-namespace:MauiPicker" x:Class="MauiPicker.MainPage" x:DataType="viewModels:MainViewModel"> <Grid ColumnDefinitions="*" RowDefinitions="*,*"> <CollectionView Grid.Row="0" Grid.Column="0" ItemsSource="{Binding PartAResultLists}" SelectionMode="None"> <CollectionView.ItemTemplate> <DataTemplate x:DataType="models:PartAResultList"> <Grid Padding="5"> <Border> <Grid Padding="10" ColumnDefinitions="Auto,*" RowDefinitions="Auto" RowSpacing="7"> <Label Text="Outlet Type:" Grid.Column="0" Grid.Row="0" HorizontalOptions="End" VerticalOptions="Center" Margin="0,0,0,0"/> <Border Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2"> <Picker Title="Select an Outlet" ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MainViewModel}}, Path=Outlets}" ItemDisplayBinding="{Binding Name}" SelectedIndex="{Binding OutletIndex}" SelectedItem="{Binding OutletName}"> </Picker> </Border> </Grid> </Border> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> <Button Grid.Row="1" Grid.Column="0" Text="Reload List" HorizontalOptions="Center" VerticalOptions="Center" Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MainViewModel}}, Path=LoadResultsCommand}"> </Button> </Grid> </ContentPage>
MainPage.xml.cs 背后的代码

namespace MauiPicker; public partial class MainPage : ContentPage { public MainPage(MainViewModel vm) { InitializeComponent(); BindingContext = vm; } }
ViewModel MainViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MvvmHelpers; namespace MauiPicker { public partial class MainViewModel : CommunityToolkit.Mvvm.ComponentModel.ObservableObject { public MainViewModel() { LoadResults(); } [RelayCommand] async Task LoadResults() { Outlets = new ObservableRangeCollection<Outlet> { new Outlet(){Name="Outlet0"}, new Outlet(){Name="Outlet1"}, new Outlet(){Name="Outlet2"}, }; PartAResultLists = new ObservableRangeCollection<PartAResultList> { new PartAResultList(){OutletIndex = 0, OutletName= new Outlet(){Name="Outlet0" } }, new PartAResultList(){OutletIndex=1, OutletName= new Outlet(){Name="Outlet1" }}, new PartAResultList(){OutletIndex = 2, OutletName= new Outlet(){Name="Outlet2" }}, new PartAResultList(){OutletIndex = 0, OutletName= new Outlet(){Name="Outlet0" }}, new PartAResultList(){OutletIndex = 2, OutletName= new Outlet(){Name="Outlet2" }} }; } [ObservableProperty] ObservableRangeCollection<Outlet> outlets; [ObservableProperty] ObservableRangeCollection<PartAResultList> partAResultLists; } }
模型;

using CommunityToolkit.Mvvm.ComponentModel; namespace MauiPicker { public partial class Outlet : ObservableObject { [ObservableProperty] public string name; } }
using CommunityToolkit.Mvvm.ComponentModel;

namespace MauiPicker
{
    public partial class PartAResultList : ObservableObject
    {

        [ObservableProperty]
        public Outlet outletName;

        [ObservableProperty]
        public int outletIndex;

    }
}
MauiProgram.cs

using CommunityToolkit.Maui; using Microsoft.Extensions.Logging; namespace MauiPicker; public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); builder.Services.AddSingleton<MainPage>(); builder.Services.AddSingleton<MainViewModel>(); #if DEBUG builder.Logging.AddDebug(); #endif return builder.Build(); } }
    
maui picker selectedindex
1个回答
0
投票
首先我想指出,对于任何正在阅读本文的人,问题中的代码绑定正确。

第二,我想说new Outlet(Name="1") 和new Outlet(Name="1") 不相等。仅仅因为某些属性具有相同的值,并不意味着对象将相同。他们是在两个不同的地方得救的,他们是不一样的。除非您在检查它们是否相等时确保只有“名称”很重要。

第三,如果您查看社区工具包 MVVM 自动生成的属性代码,您将看到如下内容:

if(!global::System.Collections.Generic.EqualityComparer<string>.Default.Equals(name, value))
并在该 IF 块中调用 OnChanged。这是优化,以帮助仅在必须重新渲染某些内容时浪费资源。

这就是为什么,当你设置:

new PartAResultList(){OutletIndex = 0...
然后如果你打电话,例如:

PartAResultLists[0].OutletIndex = 0;
选择器将保持空白。但是如果你这样称呼:

PartAResultLists[0].OutletIndex = 1;
令人惊讶的是它会改变。
(再次以索引为例,因为该对象由于我之前指出的原因而无法工作)。

不需要同时绑定到Object和Index。在您的情况下,这只会导致更多错误。

您的绑定已设置好。你必须到处修改你的代码。

编辑:您不必实际更改该值。只是试图解释未调用 OnPropertyChanged("OutletIndex") 的问题。

理论例子:假设在:

public partial class PartAResultList : ObservableObject
我们放置一些方法:

NotifyWorkaround(){ OnPropertyChanged("OutletIndex"); }
我们现在可以为列表的每个第 n 个元素调用 PartAResultList[n].NotifyWorkaround()。并且界面会响应变化。

然而,我从未在生产中使用过它。它适用于您的示例(我添加了 10 个元素),但我不知道它会对列表中的 1000、10k 或更多元素产生什么影响。

© www.soinside.com 2019 - 2024. All rights reserved.