我无法使 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();
}
}
第二,我想说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 或更多元素产生什么影响。