Modify Android and iOS adapters to handle null items sources (#4536) fixes #4366
authorE.Z. Hart <hartez@users.noreply.github.com>
Thu, 29 Nov 2018 13:03:21 +0000 (06:03 -0700)
committerRui Marinho <me@ruimarinho.net>
Thu, 29 Nov 2018 13:03:21 +0000 (13:03 +0000)
* Modify Android and iOS adapters to handle null items sources; fixes #4366

* Correct behavior for EmptySource indexer on iOS

12 files changed:
Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewGallery.cs
Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml [new file with mode: 0644]
Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
Xamarin.Forms.Platform.Android/CollectionView/EmptySource.cs [new file with mode: 0644]
Xamarin.Forms.Platform.Android/CollectionView/ItemsSourceFactory.cs
Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
Xamarin.Forms.Platform.iOS/CollectionView/CollectionViewController.cs
Xamarin.Forms.Platform.iOS/CollectionView/CollectionViewRenderer.cs
Xamarin.Forms.Platform.iOS/CollectionView/EmptySource.cs [new file with mode: 0644]
Xamarin.Forms.Platform.iOS/CollectionView/ItemsSourceFactory.cs
Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.csproj

index f4e9ad7..eee6451 100644 (file)
@@ -16,6 +16,8 @@
                                        Children =
                                        {
                                                descriptionLabel,
+                                               GalleryBuilder.NavButton("EmptyView (null ItemsSource)", () =>
+                                                       new EmptyViewNullGallery(), Navigation),
                                                GalleryBuilder.NavButton("EmptyView (String)", () =>
                                                        new EmptyViewStringGallery(), Navigation),
                                                GalleryBuilder.NavButton("EmptyView (View)", () =>
diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml
new file mode 100644 (file)
index 0000000..ea695e9
--- /dev/null
@@ -0,0 +1,15 @@
+<?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="Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries.EmptyViewNullGallery">
+    <ContentPage.Content>
+                       <CollectionView x:Name="CollectionView">
+                               <CollectionView.ItemsLayout>
+                                       <GridItemsLayout Span="3" Orientation="Vertical"></GridItemsLayout>
+                               </CollectionView.ItemsLayout>
+                               <CollectionView.EmptyView>
+                                       Nothing to display.
+                               </CollectionView.EmptyView>
+                       </CollectionView>
+    </ContentPage.Content>
+</ContentPage>
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewNullGallery.xaml.cs
new file mode 100644 (file)
index 0000000..fb88353
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries
+{
+       [XamlCompilation(XamlCompilationOptions.Compile)]
+       public partial class EmptyViewNullGallery : ContentPage
+       {
+               public EmptyViewNullGallery()
+               {
+                       InitializeComponent();
+               }
+       }
+}
\ No newline at end of file
index 3151f4f..d7955fd 100644 (file)
@@ -48,7 +48,7 @@
     <PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
     <PackageReference Include="Xam.Plugin.DeviceInfo" Version="3.0.2" />
   </ItemGroup>
-  
+
   <Target Name="CreateControllGalleryConfig" BeforeTargets="Build">
     <CreateItem Include="blank.config">
       <Output TaskParameter="Include" ItemName="ConfigFile" />
diff --git a/Xamarin.Forms.Platform.Android/CollectionView/EmptySource.cs b/Xamarin.Forms.Platform.Android/CollectionView/EmptySource.cs
new file mode 100644 (file)
index 0000000..8ad6400
--- /dev/null
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+       internal class EmptySource : IItemsViewSource
+       {
+               public int Count => 0;
+
+               public object this[int index] => throw new IndexOutOfRangeException("IItemsViewSource is empty");
+       }
+}
\ No newline at end of file
index 3af67ce..77b8273 100644 (file)
@@ -9,6 +9,11 @@ namespace Xamarin.Forms.Platform.Android
        {
                public static IItemsViewSource Create(IEnumerable itemsSource, RecyclerView.Adapter adapter)
                {
+                       if (itemsSource == null)
+                       {
+                               return new EmptySource();
+                       }
+
                        switch (itemsSource)
                        {
                                case IList _ when itemsSource is INotifyCollectionChanged:
index 05153e7..7f016cd 100644 (file)
@@ -75,6 +75,7 @@
     <Compile Include="BorderBackgroundManager.cs" />
     <Compile Include="CollectionView\CarouselViewRenderer.cs" />
     <Compile Include="CollectionView\DataChangeObserver.cs" />
+    <Compile Include="CollectionView\EmptySource.cs" />
     <Compile Include="CollectionView\EmptyViewAdapter.cs" />
     <Compile Include="CollectionView\ItemsViewAdapter.cs" />
     <Compile Include="CollectionView\EdgeSnapHelper.cs" />
index 06a1bc7..8b5c38c 100644 (file)
@@ -150,8 +150,12 @@ namespace Xamarin.Forms.Platform.iOS
 
                UICollectionViewCell GetPrototype()
                {
+                       if (_itemsSource.Count == 0)
+                       {
+                               return null;
+                       }
+
                        // TODO hartez assuming this works, we'll need to evaluate using this nsindexpath (what about groups?)
-                       // TODO hartez Also, what about situations where there is no data which matches the path?
                        var indexPath = NSIndexPath.Create(0, 0);
                        return GetCell(CollectionView, indexPath);
                }
index 49ff860..825f5a3 100644 (file)
@@ -14,7 +14,6 @@ namespace Xamarin.Forms.Platform.iOS
                }
        }
 
-       // TODO hartez 2018/05/30 08:58:42 This follows the same basic scheme as RecyclerView.Adapter; you should be able to reuse the same wrapper class for the IEnumerable   
        //// TODO hartez 2018/05/30 09:05:38 Think about whether this Controller and/or the new Adapter should be internal or public
        public class CollectionViewRenderer : ViewRenderer<CollectionView, UIView>
        {
diff --git a/Xamarin.Forms.Platform.iOS/CollectionView/EmptySource.cs b/Xamarin.Forms.Platform.iOS/CollectionView/EmptySource.cs
new file mode 100644 (file)
index 0000000..74b4ae8
--- /dev/null
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+       internal class EmptySource : IItemsViewSource
+       {
+               public int Count => 0;
+
+               public object this[int index] => throw new IndexOutOfRangeException("IItemsViewSource is empty");
+       }
+}
\ No newline at end of file
index fa58ff9..0a73ea7 100644 (file)
@@ -9,6 +9,11 @@ namespace Xamarin.Forms.Platform.iOS
        {
                public static IItemsViewSource Create(IEnumerable itemsSource, UICollectionView collectionView)
                {
+                       if (itemsSource == null)
+                       {
+                               return new EmptySource();
+                       }
+
                        switch (itemsSource)
                        {
                                case IList _ when itemsSource is INotifyCollectionChanged:
index bb28f74..912346c 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Extensions\CellExtensions.cs" />
     <Compile Include="CADisplayLinkTicker.cs" />
+    <Compile Include="CollectionView\EmptySource.cs" />
     <Compile Include="CollectionView\IItemsViewSource.cs" />
     <Compile Include="CollectionView\ItemsSourceFactory.cs" />
     <Compile Include="CollectionView\ItemsViewCell.cs" />