【问题标题】:cant load data from picker on first page load but when visiting page second time picker loads as expected无法在第一页加载时从选择器加载数据,但在第二次访问页面时选择器按预期加载
【发布时间】:2021-08-13 01:36:30
【问题描述】:

我有一个显示产品列表的 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);
            }
        }
    }

【问题讨论】:

  • 首先,如果问题出在您的 Picker 上,您为什么不发布该代码?其次,您在 XAML 中定义 BindingContext 背后的代码。选择一个或另一个,而不是两个
  • 正如@Jason 所说,您已将页面 BindingContext 设置了两次。而且您还没有使用选择器发布 xaml 代码。我们不能使用上面的代码来制作一个 repro 示例。
  • @Jason 嗨!感谢您的帮助,我添加了完整的 xaml 页面代码并删除了 XAML 中绑定上下文的定义
  • @NicoZhu-MSFT 你好!感谢您的帮助,我添加了完整的 xaml 页面代码并删除了 XAML 中绑定上下文的定义
  • 您是否在向其添加数据时重新初始化TipProizvodaList,还是一直使用Add() 方法?

标签: c# xamarin xamarin.forms uwp-xaml


【解决方案1】:

多年来,我在尝试在 OnAppearing 中做任何会影响屏幕显示内容的事情时遇到了各种问题。

Xamarin 必须在 OnAppearing 之后执行某些操作,使页面进入有效状态以接收绑定更改。

解决此限制的一种方法是延迟您想要完成的工作,以便OnAppearing 返回您的工作设置绑定之前。

这样做的“缺点”是该页面(起初)在没有您的工作的情况下会出现。请参阅对“activityIndi​​cator”的两个引用 - 在您的工作准备就绪之前,您可以控制希望用户看到的内容。

这样做的“好处”是它确保 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。显示完整性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多