c# - 无法在第一页加载时从选择器加载数据,但在第二次访问页面时选择器按预期加载
问题描述
我有一个显示产品列表的 xamarin 页面和一个代表产品类型的选择器。我的问题是,当我启动应用程序并第一次尝试访问页面时,
在调试模式下,我可以看到我正在使用的列表,因为 ItemsSource 具有价值,
但是当页面加载时,选择器显示为灰色并且没有任何数据。
当我用选择器离开页面并第二次打开它时,选择器已加载数据!
这是我的代码!
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Converters="clr-namespace:eProdaja.Mobile.Converters"
mc:Ignorable="d"
x:Class="Restoran.Mobile.Views.ProizvodiPage">
<ContentPage.Resources>
<ResourceDictionary>
<Converters:ImageConverter x:Key="imgConv"></Converters:ImageConverter>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Picker ItemsSource="{Binding TipProizvodaList}" ItemDisplayBinding="{Binding Naziv}" SelectedItem="{Binding SelectedTipProizvoda}"></Picker>
<ListView ItemsSource="{Binding ProizvodiList}" ItemSelected="ListView_ItemSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10" Margin="5" HorizontalOptions="CenterAndExpand" >
<Image Source="{Binding Slika, Converter={StaticResource imgConv}}" ></Image>
<Label Text="{Binding Naziv}"
d:Text="{Binding .}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Button HorizontalOptions="Center" BorderColor="Transparent" BackgroundColor="Transparent" TextColor="OrangeRed" Text="Dodaj u košaricu"></Button>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
xaml.cs 中的代码
private ProizvodiViewModel model = null;
public ProizvodiPage()
{
InitializeComponent();
BindingContext = model = new ProizvodiViewModel();
}
protected async override void OnAppearing()
{
base.OnAppearing();
await model.Init();
}
viewModel 内的代码
public ObservableCollection<TipProizvoda> TipProizvodaList { get; set; } = new ObservableCollection<TipProizvoda>();
public async Task Init()
{
if (TipProizvodaList.Count == 0)
{
var TPList = await _tipProizvoda.Get<List<TipProizvoda>>(null);
TipProizvodaList.Clear();
TipProizvoda empty = new TipProizvoda { TipProizvodaID = 0, Naziv = "" };
TipProizvodaList.Add(empty);
foreach (var tipProizvoda in TPList)
{
TipProizvodaList.Add(tipProizvoda);
}
}
}
解决方案
多年来,我在尝试做任何OnAppearing
影响屏幕上所见内容的事情时遇到了各种问题。
Xamarin 必须在 OnAppearing 之后执行某些操作,以使页面进入有效状态以接收绑定更改。
解决此限制的一种方法是延迟您想要完成的工作,以便在您的工作设置绑定之前OnAppearing
返回。
这样做的“缺点”是页面将在没有您的工作的情况下出现(起初) 。请参阅对“activityIndicator”的两个引用 - 在您的工作准备好之前,您可以控制希望用户看到的内容。
这样做的“好处”是它确保 Xamarin“看到”您的绑定更改。(如果需要,它还提供了一个进行慢速后台工作的地方。)
尝试这个:
public partial class MyPage : ...
{
protected override void OnAppearing()
{
base.OnAppearing();
This returns immediately, allowing OnAppearing to return.
DelayWork(100, BackgroundWork, UIWork);
}
// Custom class, used to pass results from background work to UI work.
class BackgroundResult {
...
}
private void DelayWork(int milliseconds, Func<BackgroundResult> backgroundWork, Action uiWork)
{
//OPTIONAL activityIndicator.IsRunning = true;
Task.Run( () => {
// The delay ensures Xamarin page preparation has a little time, before your work begins.
// Without this delay, under some circumstances, the page might not show up as quickly.
// You might not need this.
Task.Delay(milliseconds);
// Slow work -- do nothing that affects UI.
BackgroundResult backgroundResult = BackgroundWork();
Device.BeginInvokeOnMainThread(async () => {
await uiWork(backgroundResult);
});
});
}
private BackgroundResult BackgroundWork()
{
// Slow work -- do nothing that affects UI.
...
// fill this with whatever info you need to pass to UIWork.
var backgroundResult = new BackgroundResult();
// ...
return backgroundResult;
}
private async void UIWork(BackgroundResult backgroundResult)
{
// Work that affects UI, possibly via Bindings.
await model.Init();
//OPTIONAL activityIndicator.IsRunning = false;
}
}
在您的情况下,您可能不需要 BackgroundWork 或 BackgroundResult。显示完整性。