Xamarin.Forms.CarouselView无法正常工作并出现错误:Java.Lang.IllegalArgumentException:itemView不能为null

时间:2019-03-26 20:34:56

标签: c# xaml xamarin

我正在Xamarin(Android和iOS)中进行跨平台项目。我下载了Xamarin.Forms.CarouselView,但出现错误:    Java.Lang.IllegalArgumentException:itemView不能为空

我尝试了许多方法来执行此操作,但是很多示例都在MVVM中,并且我还没有将项目转换为MVVM。我希望CarouselView首先工作。我已经尝试过为CarouselView使用其他不同的nuget包,但得到的确是奇怪的错误。这是我最能使CarouselView正常工作的地方。其他软件包甚至都不会针对某些奇怪的兼容性问题进行编译。其中也包括预发行版(我尝试过的所有三个不同的软件包!)。

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Flora.Model;
using System.Diagnostics;
using System.Collections.ObjectModel;

namespace Flora
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PlantProfilePage : ContentPage
    {
        FloraData floraData = new FloraData();
        public string familyName { get; }
        public string genusName { get; }
        public string scientificName { get; }
        public string taxonid;
        public string indianaFlora { get; set; }
        List<string> uriList { get; set; }
        ObservableCollection<FloraData.StringData> uris { get; set; }
        public PlantProfilePage(string familyName, string genusName, string scientificName, string taxonid)
        {
            InitializeComponent();
            this.familyName = familyName;
            this.genusName = genusName;
            this.scientificName = scientificName;
            this.taxonid = taxonid;
        }

        protected async override void OnAppearing()
        {
            base.OnAppearing();
            uriList = new List<string>( await floraData.WebScraper(taxonid));
            FamilyName.BindingContext = this;
            GenusName.BindingContext = this;
            ScientificName.BindingContext = this;
            indianaFlora = uriList.First();
            uriList.Remove(indianaFlora);
            Indiana_Flora_description.BindingContext = this;
            carousel.BindingContext = floraData;
            //PlantPicture.Source = uriList.First();
            int m = 0;
            uris = new ObservableCollection<FloraData.StringData>();
            foreach(var item in uriList)
            {
                if (m < 5)
                {
                    uris.Add(new FloraData.StringData { uri = item });
                    m++;
                }
            }
            Debug.WriteLine("Size of uris is " + uris.Count);
            carousel.ItemsSource = uris;
        }//OnAppearing end

    }
}
```
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Flora.PlantProfilePage"
             xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
             xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms">


    <ContentPage.Content>
        <ScrollView>
            <StackLayout VerticalOptions="Start">
                <control:CarouselView x:Name="carousel">
                    <control:CarouselView.ItemTemplate>
                        <DataTemplate>
                            <ffimageloading:CachedImage
                                x:Name="PlantPicture"
                                Source="{Binding uri}"
                                HorizontalOptions="Center"
                                VerticalOptions="Center"
                                WidthRequest="150"
                                HeightRequest="150"
                                DownsampleToViewSize="true">
                            </ffimageloading:CachedImage>
                        </DataTemplate>
                    </control:CarouselView.ItemTemplate>
                </control:CarouselView>

                <Label x:Name="FamilyName"
                       Text="{Binding familyName, StringFormat='Family: {0:F0}'}"
                       HorizontalTextAlignment="Center"
                       FontAttributes="Bold, Italic"/>
                <Label x:Name="GenusName"
                       Text="{Binding genusName, StringFormat='Genus: {0:F0}'}"
                       HorizontalTextAlignment="Center"
                       FontAttributes="Bold, Italic"/>
                <Label x:Name="ScientificName"
                       Text="{Binding scientificName, StringFormat='Scientific Name: {0:F0}'}"
                       HorizontalTextAlignment="Center"
                       FontAttributes="Bold, Italic"/>
                <Label x:Name="Indiana_Flora_description"
                       Text="{Binding indianaFlora, StringFormat='Description: {0:F0}'}"
                       HorizontalOptions="Center"
                       FontAttributes="Bold"/>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>
```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Linq;
using System.Net.Http;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Diagnostics;
using HtmlAgilityPack;

namespace Flora.Model
{
    public class FloraData
    {

        public class StringData
        {
            public string uri { get; set; }
        }
        HttpClient client = new HttpClient();
        string[] data;
        public async Task<string[]> GetData()
        {
            string uri = "https://search.idigbio.org/v2/search/records?fields=[%22scientificname%22,%22genus%22,%22family%22,%22taxonid%22]&rq={\"county\":\"floyd\",\"stateprovince\":\"Indiana\",\"kingdom\":\"plantae\"}&no_attribution=true&limit=15";
            Debug.WriteLine("uri string is: " + uri);

            try
            {
                var response = await client.GetAsync(uri);
                if (response.IsSuccessStatusCode)
                {
                    Debug.WriteLine("status 200***IsASuccess!");
                    string content = await response.Content.ReadAsStringAsync();
                    PlantObject.RootObject dynObj = JsonConvert.DeserializeObject<PlantObject.RootObject>(content);
                    Debug.WriteLine("deserialization completed...");
                    data = new string[(dynObj.items.Count * 4)];
                    Debug.WriteLine("itemCount is " + dynObj.items.Count);
                    int i = 0;
                    foreach (var data1 in dynObj.items)
                    {
                        Debug.WriteLine(i + "foreach loop iteration");
                        Debug.WriteLine("family is: " + data1.indexTerms.family);
                        data[i] = data1.indexTerms.family;
                        Debug.WriteLine("data[i] newest addition is " + data[i]);
                        Debug.WriteLine("genus is: " + data1.indexTerms.genus);
                        data[i + 1] = data1.indexTerms.family + " " + data1.indexTerms.genus;
                        Debug.WriteLine("data[i+1] newest addition is " + data[i + 1]);
                        Debug.WriteLine("scientific name is: " + data1.indexTerms.scientificname);
                        data[i + 2] = data1.indexTerms.scientificname;
                        Debug.WriteLine("data[i+2] newest addition is " + data[i + 2]);
                        Debug.WriteLine("taxonid is " + data1.indexTerms.taxonid);
                        data[i + 3] = data1.indexTerms.taxonid.ToString() + " " + data1.indexTerms.scientificname;
                        Debug.WriteLine("data[i+3] newest addition is " + data[i + 3]);
                        i = i + 4;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error retrieving Json data: " + e);
            }
            return data;
        }//GetData end"

        List<string> imageURIs = new List<string>();

        public async Task<List<string>> WebScraper(string taxonid)
        {
            //string uri = "http://midwestherbaria.org/portal/taxa/index.php?taxauthid=1&taxon="+taxonid+"&clid=";
            int i = 0;
            var html = await client.GetStringAsync(@"http://midwestherbaria.org/portal/taxa/index.php?taxauthid=1&taxon=" + taxonid + "&clid=");
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(html);

            var uriNodes = htmlDoc.DocumentNode.Descendants("div").
                Where(x => x.GetAttributeValue("class", "").Equals("tptnimg"));
            var descriptionNodes = htmlDoc.DocumentNode.Descendants("div").
                Where(x => x.GetAttributeValue("style", "").Equals("clear:both;"));
            foreach (var node in descriptionNodes)
            {
                if (i < 1)
                {
                    var descr = HtmlEntity.DeEntitize(node.InnerText);
                    imageURIs.Add(descr);
                    Debug.WriteLine("newest description is " + imageURIs.Last());
                    break;
                }
            }
            foreach (var node in uriNodes)
            {
                var uri = HtmlEntity.DeEntitize(node.Descendants("img").FirstOrDefault()?.ChildAttributes("src")
                    .FirstOrDefault()?.Value);
                imageURIs.Add(uri);
                Debug.WriteLine("imageURIs list newest item is " + imageURIs.Last());
            }

            return imageURIs;
        }
        /*
        public async Task<List<string>> GetImage(string scientificName)
        {
            string uri = "https://search.idigbio.org/v2/search/media?fields=[%22accessuri%22]&rq={\"scientificname\":\"" + scientificName + "\"}&no_attribution=true&limit=1";
            Debug.WriteLine("IMAGE: uri string is: " + uri);
            HttpClient client = new HttpClient();
            try
            {
                var response = await client.GetAsync(uri);
                if (response.IsSuccessStatusCode)
                {
                    Debug.WriteLine("IMAGE: status 200***IsASuccess!");
                    string content = await response.Content.ReadAsStringAsync();
                    PlantQuery.RootObject dynObj = Newtonsoft.Json.JsonConvert.DeserializeObject<PlantQuery.RootObject>(content);
                    Debug.WriteLine("IMAGE: deserialization completed...");
                    //imageURIs = new string[dynObj.itemCount];
                    Debug.WriteLine("IMAGE: itemCount is " + dynObj.itemCount);
                    //int i = 0;
                    foreach (var data1 in dynObj.items)
                    {
                        Debug.WriteLine("IMAGE: foreach loop iteration");
                        Debug.WriteLine("accessURI is: " + data1.indexTerms.accessuri);
                        imageURIs.Add(data1.indexTerms.accessuri);
                        Debug.WriteLine("data[i] newest addition is " + imageURIs.Last());
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error retrieving Json data: " + e);
            }
            return imageURIs;
        }//GetImage end"
        */

    }//FloraData end
}//namespace end
```

我只希望Carousel View使用FFImageLoading处理约5个uri图像,以缓存图像。

编辑: 这是五个uri的示例,将在示例uris ObservableCollection列表之一中显示:

https://static.inaturalist.org/photos/504134/medium.jpg?1379628103
https://static.inaturalist.org/photos/8784478/small.jpg?1499006293
https://api.idigbio.org/v2/media/23cbb9eb2750e80848ac95b5d2919323?size=thumbnail
https://api.idigbio.org/v2/media/c085496285be91ace0768eb517cc704b?size=thumbnail
http://swbiodiversity.org/imglib/arizona/IND/IND-0049/IND-0049216_1491615930_tn.jpg

1 个答案:

答案 0 :(得分:0)

  

Java.Lang.IllegalArgumentException:itemView不能为空

也许Source="{Binding uri}"carousel.BindingContext = floraData;无法获取数据。从使用的代码BindingContext似乎有问题,您应该检查一下。建议首先从Xaml删除标签控件,并检查CarouselView是否可以正常工作。

您还可以参考this article关于 CarouselView 。如果FloraData类是这样的:

public class FloraData
{
    public class StringData
    {
        public string uri { get; set; }
    }

    public List<StringData> uris { get; set; }

    public FloraData()
    {
        uris = new List<StringData>() { new StringData() { uri = "https://static.inaturalist.org/photos/504134/medium.jpg?1379628103" },
                                            new StringData() { uri = "https://static.inaturalist.org/photos/8784478/small.jpg?1499006293" },
                                            new StringData() { uri = "https://api.idigbio.org/v2/media/23cbb9eb2750e80848ac95b5d2919323?size=thumbnail" },
                                            new StringData() { uri = "https://api.idigbio.org/v2/media/c085496285be91ace0768eb517cc704b?size=thumbnail" },
                                            new StringData() { uri = "http://swbiodiversity.org/imglib/arizona/IND/IND-0049/IND-0049216_1491615930_tn.jpg" }};
    }
}

在ContentPage中:

FloraData floraData = new FloraData();
carousel.BindingContext = floraData;

Xaml 代码如下:

<StackLayout>
    <CarouselView x:Name="carousel" ItemsSource="{Binding uris}">
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <Image
                    x:Name="PlantPicture"
                    Source="{Binding uri}"
                    HorizontalOptions="Center"
                    VerticalOptions="Center"
                    WidthRequest="150"
                    HeightRequest="150">
                </Image>
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>
</StackLayout>

这是检查CarouselView是否工作正常的简便方法。

  

CarouselView:“ Xamarin.Forms.ItemsView”的类型初始值设定项引发了异常

如果发生此错误,您可以参考this并执行以下操作:

要开始使用Xamarin.Forms 4.0,请通过功能标志api启用MainActivity.csAppDelegate.cs中的所有新功能。

global::Xamarin.Forms.Forms.SetFlags("Shell_Experimental", "Visual_Experimental", "CollectionView_Experimental");
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);