【问题标题】:.net MAUI Picker SelectedIndex does not cause item to display.net MAUI Picker SelectedIndex 不会导致项目显示
【发布时间】:2023-02-10 07:01:42
【问题描述】:

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

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

查看 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;

    }
}

Maui程序.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();
    }
}

【问题讨论】:

  • 对不起,我不太明白你的意思。你在Picker中说的标题,但是从代码中我发现是在CollectionView。你能详细说明你想要达到的目标吗?您能否发布一个基本演示,以便我们可以在我们这边进行测试?
  • I cut and paste the SelectedIndex xml line and paste it in say one line up the Items appear in the View, but if I spin up the app again the Item is not displayed 不太明白上面几个字的意思。你能详细解释一下吗?
  • 仅仅因为您使用的是 ObservableObject,并不意味着属性是可观察的。改用字段,并用 [ObservableProperty] 注释它们。 (以及该代码的其他修复。)我什至不会对此发表评论:“我已经尝试更改 ItemSource、SelectedIndex 和 SelectedItem 的顺序”。只是不要。
  • @JessieZhang-MSFT 我遗漏了开头 <Picker xaml.我已经把它放回去了。对不起类型
  • @H.A.H.我对 PartAResultList 模型中的字段进行了如下注释; [ObservableProperty] int testPropertyIndex;仍然没有 Picker 的更新。认为它会像我记得的那样工作,现在我不得不在另一个视图中执行此操作,但仍然没有改变。老办法也没有解决问题 private int testPropertyIndex; public int TestPropertyIndex { get => testPropertyIndex; set => SetProperty(ref testPropertyIndex, value); }

标签: maui picker selectedindex


【解决方案1】:

首先,对于正在阅读本文的任何人,我想指出问题中的代码已正确绑定。

其次,我想说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。在您的情况下,这只会导致更多错误。

您的绑定设置良好。您必须到处修改它们周围的代码。

【讨论】:

    猜你喜欢
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2022-09-23
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多