From aabe44fe7d6425a545721e4a1e6e3bd3abba3b44 Mon Sep 17 00:00:00 2001 From: "E.Z. Hart" Date: Tue, 13 Nov 2018 05:49:08 -0700 Subject: [PATCH] [Enhancement] Add CollectionView progress behind feature flag (#4265) * The barest beginnings of starting a spike for LV2 * Very basic RecyclerView * Very, very basic UICollectionView * Start setting up galleries * De-duplicate some gallery code * Android horizontal layout * Very basic horizontal/vertical text lists for iOS * Vertical list views working in iOS, stashing while trying to figure out what the deal is with horizontal views and frames with heights of 1 * Working on rotation issues in iOS * Fix name of renderer in UWP; make horizontal scrolling work for horizontal lists on UWP * Set up gallery to generate different sizes of lists for testing * Respond to items source updates on UWP * Add gallery for GridLayout; Add GridLayout; begin GridLayout implementation UWP * Basic UWP gridness * Add demo page for grid layouts with text; Handle grid layout spans on UWP; handle grid layout span changes on UWP; * Implement span updates on Android grid layouts; * Ironed out most of the iOS text cell layout issues * iOS vertical/horizontal text lists now working reliably; * In progress on UWP DataTemplate stuff * Dumping the data template into the itemsource * Vertical list basically working with DataTemplate; horizontal list having image size issues * Clean up names and move classes to their own files * Adding some notes for FormsContentControl * Rolling back platform test on UWP * Fix Tizen build * Fix typo and roll back old test code * Remove old testing comments * Make basic data templates work on Android * Update measure to work horizontally * Remove old testing code * Terser rectangles * Use nameof() * Rename FormsContentControl to ItemContentControl * Use CreateRenderer instead of GetOrCreateRenderer * Clean up TemplateCodeCollectionViewGallery * Add grid galleries for templates * Nicer example templates * Create gallery to test removing items from collections * Smooth single item removal on Android * Smooth item insertion on Android * Observable collection item adds working on UWP * UWP Remove * Split files * Add gallery for snap points; start implementation of snap points on Android; * Move snap handling to separate class; implement Start snapping (horizontally) * Debugging vertical overlap issues on Android * Temporarily add IsClippedToBounds to generators to force clipping on Android * Start and End SnapHelpers are working horizontally and vertically * Consolidate some snap code on Android * Mandatory Single Snapping working for Center/Start horizontally * Throwing together scrollto gallery * Super basic "ScrollTo" implementation for Android, plus test page * Expand ScrollTo test harness; * Move ScrollToRequestEventArgs to its own file * Mostly working Carousel renderer; needs some cleanup and its own gallery pages * Carousel gallery * Naming cleanup * Make parameter name consistent * Finally some basic data template functionality for lists * Checkpoint; sort of working * Working out estimate size hacks * Working out cell optimizations * Checkpoint before some serious refactoring * Collapsing closer to a solution; text lists and grids working; template lists and grids working; uniform size hint mostly implemented; * Remove awkward Update method * No longer hard-coding list item heights estimates * Consolidate more code * Get rid of event on ItemsViewLayout * Remove public NeedsEstimate stuff * Get rid of IConstrainedCell * Watch for Span changes on iOS * Indexed ScrollTo on iOS * Implement removal/insertion of items on iOS * Handle Move, Reset, Replace on Android * Add screens to test ScrollTo Item; implement ScrollTo Item for iOS * ScrollTo Item working on Android, but only works for MakeVisible * Implement Android ScrollTo Animated ScrollToPosition * Ugly but functional non-animated scroll with ScrollToPosition * Move Scroll logic into helper class for clarity and maintenance * Fix Start snapping with grids (hard-coded span of 1) * Fix next/previous row/col snapping bug for EndSnapHelper * Remove some debug statements * Clean up example code * Fix missing delegate setting on CollectionView * Add filtering example * Watching the adapter and handling empty view from the renderer * Add debugging for all the FindViewHolder methods * Suuuuper basic but functional EmptyView * Allow EmptyView to be turned on and off * Building tests for all the EmptyView scenarios * Set Platform on EmptyView (for now) * Templated EmptyView on Android * Clean up merge errors * Require flag to use CollectionView on Android * Require flag to use CollectionView on UWP * Restore Label functionality commented out during testing * Adding a note for myself * Add flags for iOS; flags for Android CarouselView; * Remove Calabash out-commenting * Undo changes to DotSettings; remove outdated TODOs * Fix formatting * Remove debugging code; remove outdated todos; remove unnecessary comments * Undo randon VS changes * Include CollectionView in experimental renderer testing * Use correct property in nameof() call * Rename ScrollToRequestEventArgs Animate -> IsAnimated * Rename Constrain -> ConstrainTo for consistency * Add Core flags feature; add flag verification for CollectionView features * Make sure no one is subclassing native CollectionView stuff without flag * Set CollectionView flags for unit tests * Make flags depend on Application.Current * Fix iOS 9.3 exception when laying out CollectionView * Use Device.Flags * Move CV flag check to CollectionView; use Device.Flags on native platforms; * Move classes into their own files * Make CollectionView flag check method non-browseable * Remove old TODO * Remove Element.Platform sets * stubbed toolbox entries and snippets for Carousel and Collection * updated CV snippet to include layout * Remove Linq using statement * Remove unused using statement * Turn off CollectionView in Control Gallery * Move PropertyChangedEventArgsExtensions to internal on each platform * Clean up debugging code * Fix broken test setup * Remove ToString overrides * Fix broken test screen Fix broken test screen * Fix rebase errors * Update submodule * Fix rebase error --- Stubs/Xamarin.Forms.Platform.cs | 7 +- Xamarin.Forms.Build | 2 +- .../FormsAppCompatActivity.cs | 5 +- .../FlowerBuds.jpg | Bin 0 -> 5008 bytes .../Legumes.jpg | Bin 0 -> 6210 bytes .../Vegetables.jpg | Bin 0 -> 5349 bytes ...in.Forms.ControlGallery.WindowsUniversal.csproj | 3 + Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs | 1 + .../CustomRenderers.cs | 2 +- .../Resources/FlowerBuds.jpg | Bin 0 -> 5008 bytes .../Resources/Fruits.jpg | Bin 0 -> 10315 bytes .../Resources/Legumes.jpg | Bin 0 -> 6210 bytes .../Resources/Vegetables.jpg | Bin 0 -> 5349 bytes .../Xamarin.Forms.ControlGallery.iOS.csproj | 4 + Xamarin.Forms.Controls/App.cs | 2 + Xamarin.Forms.Controls/CoreGallery.cs | 3 + .../CollectionViewCoreGalleryPage.cs | 26 ++ .../CoreGalleryPages/ListViewCoreGalleryPage.cs | 3 +- .../CollectionViewGalleries/CarouselCodeGallery.cs | 51 +++ .../CollectionViewGalleries/CarouselViewGallery.cs | 28 ++ .../CollectionViewGalleries/CollectionModifier.cs | 64 +++ .../CollectionViewGallery.cs | 24 ++ .../CollectionViewGalleries/DataTemplateGallery.cs | 32 ++ .../CollectionViewGalleries/DefaultTextGallery.cs | 37 ++ .../DemoFilteredItemSource.cs | 57 +++ .../EmptyViewGalleries/EmptyViewGallery.cs | 30 ++ .../EmptyViewGalleries/EmptyViewStringGallery.xaml | 24 ++ .../EmptyViewStringGallery.xaml.cs | 26 ++ .../EmptyViewTemplateGallery.xaml | 30 ++ .../EmptyViewTemplateGallery.xaml.cs | 55 +++ .../EmptyViewGalleries/EmptyViewViewGallery.xaml | 31 ++ .../EmptyViewViewGallery.xaml.cs | 33 ++ .../CollectionViewGalleries/EnumSelector.cs | 48 +++ .../CollectionViewGalleries/ExampleTemplates.cs | 224 ++++++++++ .../FilterCollectionView.xaml | 28 ++ .../FilterCollectionView.xaml.cs | 54 +++ .../CollectionViewGalleries/ItemAdder.cs | 23 + .../CollectionViewGalleries/ItemRemover.cs | 22 + .../CollectionViewGalleries/ItemReplacer.cs | 68 +++ .../ItemsSourceGenerator.cs | 106 +++++ .../ObservableCodeCollectionViewGridGallery.cs | 58 +++ .../ObservableCollectionGallery.cs | 33 ++ .../CollectionViewGalleries/ScrollToCodeGallery.cs | 54 +++ .../CollectionViewGalleries/ScrollToGallery.cs | 47 +++ .../ScrollToIndexControl.cs | 110 +++++ .../CollectionViewGalleries/ScrollToItemControl.cs | 87 ++++ .../SnapPointsCodeGallery.cs | 59 +++ .../CollectionViewGalleries/SnapPointsGallery.cs | 34 ++ .../CollectionViewGalleries/SpanSetter.cs | 49 +++ .../TemplateCodeCollectionViewGallery.cs | 36 ++ .../TemplateCodeCollectionViewGridGallery.cs | 38 ++ .../TextCodeCollectionViewGallery.cs | 32 ++ .../TextCodeCollectionViewGridGallery.cs | 36 ++ .../GalleryPages/GalleryBuilder.cs | 14 + .../DisabledStatesGallery.cs | 21 +- .../VisualStateManagerGallery.cs | 19 +- .../Xamarin.Forms.Controls.csproj | 86 +++- .../toolbox/Xamarin.Forms.toolbox.xml | 23 + Xamarin.Forms.Core.UnitTests/ItemsViewTests.cs | 50 +++ .../Xamarin.Forms.Core.UnitTests.csproj | 1 + Xamarin.Forms.Core/Application.cs | 5 +- Xamarin.Forms.Core/Items/CarouselView.cs | 18 + Xamarin.Forms.Core/Items/CollectionView.cs | 51 +++ Xamarin.Forms.Core/Items/GridItemsLayout.cs | 25 ++ Xamarin.Forms.Core/Items/IItemsLayout.cs | 6 + Xamarin.Forms.Core/Items/ItemsLayout.cs | 33 ++ Xamarin.Forms.Core/Items/ItemsLayoutOrientation.cs | 8 + Xamarin.Forms.Core/Items/ItemsView.cs | 100 +++++ Xamarin.Forms.Core/Items/ListItemsLayout.cs | 16 + .../Items/ScrollToRequestEventArgs.cs | 44 ++ Xamarin.Forms.Core/Items/SnapPointsAlignment.cs | 9 + Xamarin.Forms.Core/Items/SnapPointsType.cs | 9 + .../CollectionView/CarouselViewRenderer.cs | 32 ++ .../CollectionView/CollectionViewRenderer.cs | 12 + .../CollectionView/DataChangeObserver.cs | 52 +++ .../CollectionView/EdgeSnapHelper.cs | 60 +++ .../CollectionView/EmptyViewAdapter.cs | 94 +++++ .../CollectionView/EndSnapHelper.cs | 71 ++++ .../CollectionView/IItemsViewSource.cs | 8 + .../CollectionView/ItemContentControl.cs | 49 +++ .../CollectionView/ItemsSourceFactory.cs | 23 + .../CollectionView/ItemsViewAdapter.cs | 129 ++++++ .../CollectionView/ItemsViewRenderer.cs | 465 +++++++++++++++++++++ .../CollectionView/ListSource.cs | 25 ++ .../CollectionView/ObservableItemsSource.cs | 97 +++++ .../CollectionView/PositionalSmoothScroller.cs | 50 +++ .../PropertyChangedEventArgsExtensions.cs | 25 ++ .../CollectionView/ScrollHelper.cs | 173 ++++++++ .../CollectionView/SizedItemContentControl.cs | 27 ++ .../CollectionView/SnapManager.cs | 88 ++++ .../CollectionView/StartPagerSnapHelper.cs | 72 ++++ .../CollectionView/StartSnapHelper.cs | 77 ++++ .../ContextExtensions.cs | 6 + .../Properties/AssemblyInfo.cs | 2 + .../Xamarin.Forms.Platform.Android.csproj | 22 +- .../CollectionViewRenderer.cs | 376 +++++++++++++++++ Xamarin.Forms.Platform.UAP/Flags.cs | 1 - Xamarin.Forms.Platform.UAP/Items/FormsGridView.cs | 68 +++ .../Items/ItemContentControl.cs | 122 ++++++ .../Items/ItemTemplateEnumerator.cs | 125 ++++++ .../Items/ItemTemplatePair.cs | 14 + .../Items/ItemsViewStyles.xaml | 47 +++ Xamarin.Forms.Platform.UAP/LabelRenderer.cs | 12 +- .../Properties/AssemblyInfo.cs | 1 + .../PropertyChangedEventArgsExtensions.cs | 25 ++ Xamarin.Forms.Platform.UAP/Resources.xaml | 1 + Xamarin.Forms.Platform.UAP/StepperControl.xaml.cs | 1 + Xamarin.Forms.Platform.UAP/TableViewRenderer.cs | 3 +- .../Xamarin.Forms.Platform.UAP.csproj | 19 +- .../CollectionView/CollectionViewController.cs | 161 +++++++ .../CollectionView/CollectionViewRenderer.cs | 185 ++++++++ .../CollectionView/DefaultCell.cs | 37 ++ .../CollectionView/DefaultHorizontalListCell.cs | 28 ++ .../CollectionView/DefaultVerticalListCell.cs | 27 ++ .../CollectionView/GridViewLayout.cs | 55 +++ .../CollectionView/IItemsViewSource.cs | 8 + .../CollectionView/ItemsSourceFactory.cs | 23 + .../CollectionView/ItemsViewCell.cs | 31 ++ .../CollectionView/ItemsViewLayout.cs | 201 +++++++++ .../CollectionView/ListSource.cs | 25 ++ .../CollectionView/ListViewLayout.cs | 19 + .../CollectionView/ObservableItemsSource.cs | 76 ++++ .../PropertyChangedEventArgsExtensions.cs | 25 ++ .../CollectionView/TemplatedCell.cs | 73 ++++ .../CollectionView/TemplatedHorizontalListCell.cs | 34 ++ .../CollectionView/TemplatedVerticalListCell.cs | 35 ++ Xamarin.Forms.Platform.iOS/Flags.cs | 1 - .../Properties/AssemblyInfo.cs | 1 + .../Xamarin.Forms.Platform.iOS.csproj | 17 + Xamarin.Forms.Platform/Xamarin.Forms.Platform.cs | 4 + 130 files changed, 5856 insertions(+), 48 deletions(-) create mode 100644 Xamarin.Forms.ControlGallery.WindowsUniversal/FlowerBuds.jpg create mode 100644 Xamarin.Forms.ControlGallery.WindowsUniversal/Legumes.jpg create mode 100644 Xamarin.Forms.ControlGallery.WindowsUniversal/Vegetables.jpg create mode 100644 Xamarin.Forms.ControlGallery.iOS/Resources/FlowerBuds.jpg create mode 100644 Xamarin.Forms.ControlGallery.iOS/Resources/Fruits.jpg create mode 100644 Xamarin.Forms.ControlGallery.iOS/Resources/Legumes.jpg create mode 100644 Xamarin.Forms.ControlGallery.iOS/Resources/Vegetables.jpg create mode 100644 Xamarin.Forms.Controls/CoreGalleryPages/CollectionViewCoreGalleryPage.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselCodeGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionModifier.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionViewGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DataTemplateGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DefaultTextGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DemoFilteredItemSource.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EnumSelector.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ExampleTemplates.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemAdder.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemRemover.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemReplacer.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemsSourceGenerator.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCodeCollectionViewGridGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCollectionGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToCodeGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToIndexControl.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToItemControl.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsCodeGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SpanSetter.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGridGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGridGallery.cs create mode 100644 Xamarin.Forms.Controls/GalleryPages/GalleryBuilder.cs create mode 100644 Xamarin.Forms.Core.UnitTests/ItemsViewTests.cs create mode 100644 Xamarin.Forms.Core/Items/CarouselView.cs create mode 100644 Xamarin.Forms.Core/Items/CollectionView.cs create mode 100644 Xamarin.Forms.Core/Items/GridItemsLayout.cs create mode 100644 Xamarin.Forms.Core/Items/IItemsLayout.cs create mode 100644 Xamarin.Forms.Core/Items/ItemsLayout.cs create mode 100644 Xamarin.Forms.Core/Items/ItemsLayoutOrientation.cs create mode 100644 Xamarin.Forms.Core/Items/ItemsView.cs create mode 100644 Xamarin.Forms.Core/Items/ListItemsLayout.cs create mode 100644 Xamarin.Forms.Core/Items/ScrollToRequestEventArgs.cs create mode 100644 Xamarin.Forms.Core/Items/SnapPointsAlignment.cs create mode 100644 Xamarin.Forms.Core/Items/SnapPointsType.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/CarouselViewRenderer.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/CollectionViewRenderer.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/DataChangeObserver.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/EdgeSnapHelper.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/EmptyViewAdapter.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/EndSnapHelper.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/IItemsViewSource.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ItemContentControl.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ItemsSourceFactory.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ItemsViewAdapter.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ItemsViewRenderer.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ListSource.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ObservableItemsSource.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/PositionalSmoothScroller.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/PropertyChangedEventArgsExtensions.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/ScrollHelper.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/SizedItemContentControl.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/SnapManager.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/StartPagerSnapHelper.cs create mode 100644 Xamarin.Forms.Platform.Android/CollectionView/StartSnapHelper.cs create mode 100644 Xamarin.Forms.Platform.UAP/CollectionViewRenderer.cs create mode 100644 Xamarin.Forms.Platform.UAP/Items/FormsGridView.cs create mode 100644 Xamarin.Forms.Platform.UAP/Items/ItemContentControl.cs create mode 100644 Xamarin.Forms.Platform.UAP/Items/ItemTemplateEnumerator.cs create mode 100644 Xamarin.Forms.Platform.UAP/Items/ItemTemplatePair.cs create mode 100644 Xamarin.Forms.Platform.UAP/Items/ItemsViewStyles.xaml create mode 100644 Xamarin.Forms.Platform.UAP/PropertyChangedEventArgsExtensions.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/CollectionViewController.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/CollectionViewRenderer.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/DefaultCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/DefaultHorizontalListCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/DefaultVerticalListCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/GridViewLayout.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/IItemsViewSource.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ItemsSourceFactory.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ItemsViewCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ItemsViewLayout.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ListSource.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ListViewLayout.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/ObservableItemsSource.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/PropertyChangedEventArgsExtensions.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/TemplatedCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/TemplatedHorizontalListCell.cs create mode 100644 Xamarin.Forms.Platform.iOS/CollectionView/TemplatedVerticalListCell.cs diff --git a/Stubs/Xamarin.Forms.Platform.cs b/Stubs/Xamarin.Forms.Platform.cs index d5b07c6..d45b57c 100644 --- a/Stubs/Xamarin.Forms.Platform.cs +++ b/Stubs/Xamarin.Forms.Platform.cs @@ -63,7 +63,12 @@ namespace Xamarin.Forms.Platform [RenderWith (typeof (ListViewRenderer))] internal class _ListViewRenderer { } - +#if !TIZEN4_0 + [RenderWith (typeof (CollectionViewRenderer))] + internal class _CollectionViewRenderer { } + [RenderWith (typeof (CarouselViewRenderer))] + internal class _CarouselViewRenderer { } +#endif [RenderWith (typeof (SliderRenderer))] internal class _SliderRenderer { } diff --git a/Xamarin.Forms.Build b/Xamarin.Forms.Build index 8f864cf..1821d28 160000 --- a/Xamarin.Forms.Build +++ b/Xamarin.Forms.Build @@ -1 +1 @@ -Subproject commit 8f864cf6b0c9e7b1973bee04e5fd81933067163e +Subproject commit 1821d28a3ae711cffb7721ff0d595bb0128e6036 diff --git a/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs b/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs index 9b2f0fb..510476e 100644 --- a/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs +++ b/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs @@ -41,9 +41,12 @@ namespace Xamarin.Forms.ControlGallery.Android base.OnCreate(bundle); #if TEST_EXPERIMENTAL_RENDERERS + // CollectionView lets us test CollectionView stuff until it's officially released Forms.SetFlags("FastRenderers_Experimental"); #else - Forms.SetFlags("Fake_Flag"); // So we can test for flag initialization issues + // Fake_Flag is here so we can test for flag initialization issues + // CollectionView lets us test CollectionView stuff until it's officially released + Forms.SetFlags("Fake_Flag"); #endif Forms.Init(this, bundle); diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/FlowerBuds.jpg b/Xamarin.Forms.ControlGallery.WindowsUniversal/FlowerBuds.jpg new file mode 100644 index 0000000000000000000000000000000000000000..023797cc106124e0aadbfb14a87babcb501819b2 GIT binary patch literal 5008 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 y*YTehv9G&aIS=b_CtN#tx%4kdCQAVT literal 0 HcmV?d00001 diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Legumes.jpg b/Xamarin.Forms.ControlGallery.WindowsUniversal/Legumes.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f299b41a624b4dd27bb37ed5896699720ce7867 GIT binary patch literal 6210 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 I?)BV%01N2u0ssI2 literal 0 HcmV?d00001 diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Vegetables.jpg b/Xamarin.Forms.ControlGallery.WindowsUniversal/Vegetables.jpg new file mode 100644 index 0000000000000000000000000000000000000000..297964d72689045c4677598dfc2dd09fd6e9393e GIT binary patch literal 5349 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 + + @@ -151,6 +153,7 @@ + diff --git a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs index 3b8710a..994d561 100644 --- a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs +++ b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs @@ -159,6 +159,7 @@ namespace Xamarin.Forms.ControlGallery.iOS App.IOSVersion = int.Parse(versionPart[0]); Xamarin.Calabash.Start(); + Forms.Init(); FormsMaps.Init(); Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) => diff --git a/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs index 33d4265..e70ffee 100644 --- a/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs +++ b/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs @@ -12,7 +12,7 @@ using Xamarin.Forms.Controls.Issues; using Xamarin.Forms.Platform.iOS; using RectangleF = CoreGraphics.CGRect; -[assembly: ExportRenderer(typeof(Bugzilla21177.CollectionView), typeof(CollectionViewRenderer))] +[assembly: ExportRenderer(typeof(Bugzilla21177.CollectionView), typeof(Xamarin.Forms.ControlGallery.iOS.CollectionViewRenderer))] [assembly: ExportRenderer(typeof(Bugzilla31395.CustomContentView), typeof(CustomContentRenderer))] [assembly: ExportRenderer(typeof(NativeCell), typeof(NativeiOSCellRenderer))] [assembly: ExportRenderer(typeof(NativeListView2), typeof(NativeiOSListViewRenderer))] diff --git a/Xamarin.Forms.ControlGallery.iOS/Resources/FlowerBuds.jpg b/Xamarin.Forms.ControlGallery.iOS/Resources/FlowerBuds.jpg new file mode 100644 index 0000000000000000000000000000000000000000..023797cc106124e0aadbfb14a87babcb501819b2 GIT binary patch literal 5008 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 y*YTehv9G&aIS=b_CtN#tx%4kdCQAVT literal 0 HcmV?d00001 diff --git a/Xamarin.Forms.ControlGallery.iOS/Resources/Fruits.jpg b/Xamarin.Forms.ControlGallery.iOS/Resources/Fruits.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6c4ea3d9ff97e7e4e4ebb34f7b64a7114054ed86 GIT binary patch literal 10315 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 I?)BV%01N2u0ssI2 literal 0 HcmV?d00001 diff --git a/Xamarin.Forms.ControlGallery.iOS/Resources/Vegetables.jpg b/Xamarin.Forms.ControlGallery.iOS/Resources/Vegetables.jpg new file mode 100644 index 0000000000000000000000000000000000000000..297964d72689045c4677598dfc2dd09fd6e9393e GIT binary patch literal 5349 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 + + + + diff --git a/Xamarin.Forms.Controls/App.cs b/Xamarin.Forms.Controls/App.cs index 9f4d9e7..86f76ce 100644 --- a/Xamarin.Forms.Controls/App.cs +++ b/Xamarin.Forms.Controls/App.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading.Tasks; diff --git a/Xamarin.Forms.Controls/CoreGallery.cs b/Xamarin.Forms.Controls/CoreGallery.cs index c492b16..419278f 100644 --- a/Xamarin.Forms.Controls/CoreGallery.cs +++ b/Xamarin.Forms.Controls/CoreGallery.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xamarin.Forms.Controls.GalleryPages; +using Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries; using Xamarin.Forms.CustomAttributes; using Xamarin.Forms.Internals; using Xamarin.Forms.PlatformConfiguration; @@ -270,6 +271,8 @@ namespace Xamarin.Forms.Controls } List _pages = new List { + new GalleryPageFactory(() => new CollectionViewGallery(), "CollectionView Gallery"), + new GalleryPageFactory(() => new CollectionViewCoreGalleryPage(), "CollectionView Core Gallery"), new GalleryPageFactory(() => new Issues.PerformanceGallery(), "Performance"), new GalleryPageFactory(() => new EntryReturnTypeGalleryPage(), "Entry ReturnType "), new GalleryPageFactory(() => new VisualStateManagerGallery(), "VisualStateManager Gallery"), diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/CollectionViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/CollectionViewCoreGalleryPage.cs new file mode 100644 index 0000000..b29f0c1 --- /dev/null +++ b/Xamarin.Forms.Controls/CoreGalleryPages/CollectionViewCoreGalleryPage.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace Xamarin.Forms.Controls +{ + internal class CollectionViewCoreGalleryPage : CoreGalleryPage + { + protected override void InitializeElement(CollectionView element) + { + base.InitializeElement(element); + + var items = new List(); + + for (int n = 0; n < 1000; n++) + { + items.Add(DateTime.Now.AddDays(n).ToLongDateString()); + } + + element.ItemsSource = items; + + element.HeightRequest = 250; + + element.ItemsLayout = ListItemsLayout.VerticalList; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs index 216e1bd..8255ccb 100644 --- a/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs +++ b/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs @@ -4,9 +4,8 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; -using System.Threading; - using Xamarin.Forms.CustomAttributes; +using System.Threading; using Xamarin.Forms.Internals; using Xamarin.Forms.PlatformConfiguration; diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselCodeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselCodeGallery.cs new file mode 100644 index 0000000..60e1baa --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselCodeGallery.cs @@ -0,0 +1,51 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class CarouselCodeGallery : ContentPage + { + public CarouselCodeGallery(ItemsLayoutOrientation orientation) + { + Title = $"CarouselView (Code, {orientation})"; + + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var itemsLayout = + new ListItemsLayout(orientation) + { + SnapPointsType = SnapPointsType.MandatorySingle, + SnapPointsAlignment = SnapPointsAlignment.Center + }; + + var itemTemplate = ExampleTemplates.CarouselTemplate(); + + var carouselView = new CarouselView + { + ItemsLayout = itemsLayout, + ItemTemplate = itemTemplate, + }; + + var generator = new ItemsSourceGenerator(carouselView, initialItems: 50); + + layout.Children.Add(generator); + + var scrollToControl = new ScrollToIndexControl(carouselView, false); + layout.Children.Add(scrollToControl); + + layout.Children.Add(carouselView); + + Grid.SetRow(scrollToControl, 1); + Grid.SetRow(carouselView, 2); + + Content = layout; + + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGallery.cs new file mode 100644 index 0000000..2a9d0d0 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGallery.cs @@ -0,0 +1,28 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class CarouselViewGallery : ContentPage + { + public CarouselViewGallery() + { + var descriptionLabel = + new Label { Text = "CarouselView Galleries", Margin = new Thickness(2, 2, 2, 2) }; + + Title = "CarouselView Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + GalleryBuilder.NavButton("CarouselView (Code, Horizontal)", () => + new CarouselCodeGallery(ItemsLayoutOrientation.Horizontal), Navigation), + GalleryBuilder.NavButton("CarouselView (Code, Vertical)", () => + new CarouselCodeGallery(ItemsLayoutOrientation.Vertical), Navigation) + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionModifier.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionModifier.cs new file mode 100644 index 0000000..1439cfd --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionModifier.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.ObjectModel; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal abstract class CollectionModifier : ContentView + { + readonly CollectionView _cv; + protected readonly Entry Entry; + + protected CollectionModifier (CollectionView cv, string buttonText) + { + _cv = cv; + + var layout = new StackLayout + { + Orientation = StackOrientation.Horizontal, + HorizontalOptions = LayoutOptions.Fill + }; + + var button = new Button { Text = buttonText }; + var label = new Label { Text = "Index:", VerticalTextAlignment = TextAlignment.Center }; + + Entry = new Entry { Keyboard = Keyboard.Numeric, Text = "0", WidthRequest = 200 }; + + layout.Children.Add(label); + layout.Children.Add(Entry); + layout.Children.Add(button); + + button.Clicked += ButtonOnClicked; + + Content = layout; + } + + void ButtonOnClicked(object sender, EventArgs e) + { + if (!ParseIndexes(out int[] indexes)) + { + return; + } + + if (!(_cv.ItemsSource is ObservableCollection observableCollection)) + { + return; + } + + ModifyCollection(observableCollection, indexes); + } + + protected virtual bool ParseIndexes(out int[] indexes) + { + if (!int.TryParse(Entry.Text, out int index)) + { + indexes = new int[0]; + return false; + } + + indexes = new[] {index}; + return true; + } + + protected abstract void ModifyCollection(ObservableCollection observableCollection, params int[] indexes); + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionViewGallery.cs new file mode 100644 index 0000000..243104f --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CollectionViewGallery.cs @@ -0,0 +1,24 @@ +using Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + public class CollectionViewGallery : ContentPage + { + public CollectionViewGallery() + { + Content = new StackLayout + { + Children = + { + GalleryBuilder.NavButton("Default Text Galleries", () => new DefaultTextGallery(), Navigation), + GalleryBuilder.NavButton("DataTemplate Galleries", () => new DataTemplateGallery(), Navigation), + GalleryBuilder.NavButton("Observable Collection Galleries", () => new ObservableCollectionGallery(), Navigation), + GalleryBuilder.NavButton("Snap Points Galleries", () => new SnapPointsGallery(), Navigation), + GalleryBuilder.NavButton("ScrollTo Galleries", () => new ScrollToGallery(), Navigation), + GalleryBuilder.NavButton("CarouselView Galleries", () => new CarouselViewGallery(), Navigation), + GalleryBuilder.NavButton("EmptyView Galleries", () => new EmptyViewGallery(), Navigation), + } + }; + } + } +} diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DataTemplateGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DataTemplateGallery.cs new file mode 100644 index 0000000..f171994 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DataTemplateGallery.cs @@ -0,0 +1,32 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class DataTemplateGallery : ContentPage + { + public DataTemplateGallery() + { + var descriptionLabel = + new Label { Text = "Simple DataTemplate Galleries", Margin = new Thickness(2, 2, 2, 2) }; + + Title = "Simple DataTemplate Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + GalleryBuilder.NavButton("Vertical List (Code)", () => + new TemplateCodeCollectionViewGallery(ListItemsLayout.VerticalList), Navigation), + GalleryBuilder.NavButton("Horizontal List (Code)", () => + new TemplateCodeCollectionViewGallery(ListItemsLayout.HorizontalList), Navigation), + GalleryBuilder.NavButton("Vertical Grid (Code)", () => + new TemplateCodeCollectionViewGridGallery (), Navigation), + GalleryBuilder.NavButton("Horizontal Grid (Code)", () => + new TemplateCodeCollectionViewGridGallery (ItemsLayoutOrientation.Horizontal), Navigation), + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DefaultTextGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DefaultTextGallery.cs new file mode 100644 index 0000000..8e3ec86 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DefaultTextGallery.cs @@ -0,0 +1,37 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class DefaultTextGallery : ContentPage + { + public DefaultTextGallery() + { + var descriptionLabel = new Label + { + Text = "No DataTemplates; just using the ToString() of the objects in the source.", + Margin = new Thickness(2, 2, 2, 2) + }; + + Title = "Default Text Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + // TODO hartez 2018-06-05 10:43 AM Need a gallery page which allows layout selection + // so we can demonstrate switching between them + descriptionLabel, + GalleryBuilder.NavButton("Vertical List (Code)", () => + new TextCodeCollectionViewGallery(ListItemsLayout.VerticalList), Navigation), + GalleryBuilder.NavButton("Horizontal List (Code)", () => + new TextCodeCollectionViewGallery(ListItemsLayout.HorizontalList), Navigation), + GalleryBuilder.NavButton("Vertical Grid (Code)", () => + new TextCodeCollectionViewGridGallery(), Navigation), + GalleryBuilder.NavButton("Horizontal Grid (Code)", () => + new TextCodeCollectionViewGridGallery(ItemsLayoutOrientation.Horizontal), Navigation), + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DemoFilteredItemSource.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DemoFilteredItemSource.cs new file mode 100644 index 0000000..aad50bb --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/DemoFilteredItemSource.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class DemoFilteredItemSource + { + readonly List _source; + + public ObservableCollection Items { get; } + + public DemoFilteredItemSource() + { + _source = new List(); + var count = 50; + string[] images = + { + "cover1.jpg", + "oasis.jpg", + "photo.jpg", + "Vegetables.jpg", + "Fruits.jpg", + "FlowerBuds.jpg", + "Legumes.jpg" + }; + + for (int n = 0; n < count; n++) + { + _source.Add(new CollectionViewGalleryTestItem(DateTime.Now.AddDays(n), + $"{images[n % images.Length]}, {n}", images[n % images.Length], n)); + } + Items = new ObservableCollection(_source); + } + + public void FilterItems(string filter) + { + var filteredItems = _source.Where(item => item.Caption.ToLower().Contains(filter.ToLower())).ToList(); + + foreach (CollectionViewGalleryTestItem collectionViewGalleryTestItem in _source) + { + if (!filteredItems.Contains(collectionViewGalleryTestItem)) + { + Items.Remove(collectionViewGalleryTestItem); + } + else + { + if (!Items.Contains(collectionViewGalleryTestItem)) + { + Items.Add(collectionViewGalleryTestItem); + } + } + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewGallery.cs new file mode 100644 index 0000000..f4e9ad7 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewGallery.cs @@ -0,0 +1,30 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries +{ + internal class EmptyViewGallery : ContentPage + { + public EmptyViewGallery() + { + var descriptionLabel = + new Label { Text = "EmptyView Galleries", Margin = new Thickness(2, 2, 2, 2) }; + + Title = "EmptyView Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + GalleryBuilder.NavButton("EmptyView (String)", () => + new EmptyViewStringGallery(), Navigation), + GalleryBuilder.NavButton("EmptyView (View)", () => + new EmptyViewViewGallery(), Navigation), + GalleryBuilder.NavButton("EmptyView (Template View)", () => + new EmptyViewTemplateGallery(), Navigation) + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml new file mode 100644 index 0000000..b851a41 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + No items match your filter. + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml.cs new file mode 100644 index 0000000..2066f83 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewStringGallery.xaml.cs @@ -0,0 +1,26 @@ +using Xamarin.Forms.Xaml; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class EmptyViewStringGallery : ContentPage + { + readonly DemoFilteredItemSource _demoFilteredItemSource = new DemoFilteredItemSource(); + + public EmptyViewStringGallery() + { + InitializeComponent(); + + CollectionView.ItemTemplate = ExampleTemplates.PhotoTemplate(); + + CollectionView.ItemsSource = _demoFilteredItemSource.Items; + + SearchBar.TextChanged += SearchBarOnTextChanged; + } + + void SearchBarOnTextChanged(object sender, TextChangedEventArgs e) + { + _demoFilteredItemSource.FilterItems(e.NewTextValue); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml new file mode 100644 index 0000000..da35604 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml.cs new file mode 100644 index 0000000..a142ffb --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewTemplateGallery.xaml.cs @@ -0,0 +1,55 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Xamarin.Forms.Internals; +using Xamarin.Forms.Xaml; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.EmptyViewGalleries +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class EmptyViewTemplateGallery : ContentPage + { + readonly DemoFilteredItemSource _demoFilteredItemSource = new DemoFilteredItemSource(); + readonly EmptyViewGalleryFilterInfo _emptyViewGalleryFilterInfo = new EmptyViewGalleryFilterInfo(); + + public EmptyViewTemplateGallery () + { + InitializeComponent (); + + CollectionView.ItemTemplate = ExampleTemplates.PhotoTemplate(); + + CollectionView.ItemsSource = _demoFilteredItemSource.Items; + CollectionView.EmptyView = _emptyViewGalleryFilterInfo; + + SearchBar.TextChanged += SearchBarOnTextChanged; + } + + void SearchBarOnTextChanged(object sender, TextChangedEventArgs e) + { + _demoFilteredItemSource.FilterItems(e.NewTextValue); + _emptyViewGalleryFilterInfo.Filter = e.NewTextValue; + } + } + + [Preserve(AllMembers = true)] + public class EmptyViewGalleryFilterInfo : INotifyPropertyChanged + { + string _filter; + + public string Filter + { + get => _filter; + set + { + _filter = value; + OnPropertyChanged(); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml new file mode 100644 index 0000000..b800c69 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml.cs new file mode 100644 index 0000000..07fad78 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EmptyViewGalleries/EmptyViewViewGallery.xaml.cs @@ -0,0 +1,33 @@ +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 EmptyViewViewGallery : ContentPage + { + readonly DemoFilteredItemSource _demoFilteredItemSource = new DemoFilteredItemSource(); + + public EmptyViewViewGallery () + { + InitializeComponent (); + + CollectionView.ItemTemplate = ExampleTemplates.PhotoTemplate(); + + CollectionView.ItemsSource = _demoFilteredItemSource.Items; + + SearchBar.TextChanged += SearchBarOnTextChanged; + } + + void SearchBarOnTextChanged(object sender, TextChangedEventArgs e) + { + _demoFilteredItemSource.FilterItems(e.NewTextValue); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EnumSelector.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EnumSelector.cs new file mode 100644 index 0000000..d92c9e1 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/EnumSelector.cs @@ -0,0 +1,48 @@ +using System; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class EnumSelector : ContentView where T : struct + { + readonly Action _setValue; + + readonly Picker _picker; + + public EnumSelector(Func getValue, Action setValue) + { + _setValue = setValue; + + var layout = new StackLayout + { + Orientation = StackOrientation.Horizontal, + HorizontalOptions = LayoutOptions.Fill + }; + + var label = new Label { Text = $"{typeof(T).Name}:", VerticalTextAlignment = TextAlignment.Center }; + + var source = Enum.GetNames(typeof(T)); + + _picker = new Picker + { + WidthRequest = 200, + ItemsSource = source, + SelectedItem = getValue().ToString() + }; + + _picker.SelectedIndexChanged += PickerOnSelectedIndexChanged; + + layout.Children.Add(label); + layout.Children.Add(_picker); + + Content = layout; + } + + void PickerOnSelectedIndexChanged(object sender, EventArgs e) + { + if (Enum.TryParse(_picker.SelectedItem.ToString(), true, out T enumValue)) + { + _setValue(enumValue); + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ExampleTemplates.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ExampleTemplates.cs new file mode 100644 index 0000000..6fa8ca2 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ExampleTemplates.cs @@ -0,0 +1,224 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ExampleTemplates + { + public static DataTemplate PhotoTemplate() + { + return new DataTemplate(() => + { + var templateLayout = new Grid + { + RowDefinitions = new RowDefinitionCollection { new RowDefinition(), new RowDefinition() }, + WidthRequest = 100, + HeightRequest = 100 + }; + + var image = new Image + { + HeightRequest = 100, WidthRequest = 100, + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center + }; + + image.SetBinding(Image.SourceProperty, new Binding("Image")); + + var caption = new Label + { + FontSize = 12, + HorizontalOptions = LayoutOptions.Fill, + HorizontalTextAlignment = TextAlignment.Center + }; + + caption.SetBinding(Label.TextProperty, new Binding("Caption")); + + templateLayout.Children.Add(image); + templateLayout.Children.Add(caption); + + Grid.SetRow(caption, 1); + + return templateLayout; + }); + } + + public static DataTemplate SnapPointsTemplate() + { + return new DataTemplate(() => + { + var templateLayout = new Grid + { + RowDefinitions = new RowDefinitionCollection { new RowDefinition(), new RowDefinition {Height = GridLength.Auto} }, + WidthRequest = 100, + HeightRequest = 130 + }; + + var image = new Image + { + Margin = new Thickness(5), + HeightRequest = 100, + WidthRequest = 100, + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + Aspect = Aspect.AspectFit + }; + + image.SetBinding(Image.SourceProperty, new Binding("Image")); + + var caption = new Label + { + FontSize = 12, + HorizontalOptions = LayoutOptions.Fill, + BackgroundColor = Color.Aquamarine, + HorizontalTextAlignment = TextAlignment.Center + }; + + caption.SetBinding(Label.TextProperty, new Binding("Caption")); + + templateLayout.Children.Add(image); + templateLayout.Children.Add(caption); + + Grid.SetRow(caption, 1); + + return templateLayout; + }); + } + + public static DataTemplate CarouselTemplate() + { + return new DataTemplate(() => + { + var grid = new Grid + { + BackgroundColor = Color.LightBlue, + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition(), + new RowDefinition { Height = GridLength.Auto } + } + }; + + var image = new Image + { + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + Aspect = Aspect.AspectFill + }; + + image.SetBinding(Image.SourceProperty, new Binding("Image")); + + var caption = new Label + { + BackgroundColor = Color.Gray, + HorizontalOptions = LayoutOptions.Fill, + HorizontalTextAlignment = TextAlignment.Center, + Margin = new Thickness(5) + }; + + caption.SetBinding(Label.TextProperty, new Binding("Caption")); + + grid.Children.Add(image); + grid.Children.Add(caption); + + Grid.SetRow(caption, 1); + + var frame = new Frame + { + Padding = new Thickness(5), + Content = grid + }; + + return frame; + }); + } + + public static DataTemplate ScrollToIndexTemplate() + { + return new DataTemplate(() => + { + var templateLayout = new Grid + { + BackgroundColor = Color.Bisque, + + RowDefinitions = new RowDefinitionCollection + { new RowDefinition(), new RowDefinition { Height = GridLength.Auto } }, + WidthRequest = 100, + HeightRequest = 140 + }; + + var image = new Image + { + Margin = new Thickness(5), + HeightRequest = 100, + WidthRequest = 100, + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + Aspect = Aspect.AspectFit + }; + + image.SetBinding(Image.SourceProperty, new Binding("Image")); + + var caption = new Label + { + HorizontalOptions = LayoutOptions.Fill, + HorizontalTextAlignment = TextAlignment.Center, + HeightRequest = 40, WidthRequest = 100, + BackgroundColor = Color.Crimson, + Text = "Caption" + }; + + caption.SetBinding(Label.TextProperty, new Binding("Index", stringFormat:"Index {0}")); + + templateLayout.Children.Add(image); + templateLayout.Children.Add(caption); + + Grid.SetRow(caption, 1); + + return templateLayout; + }); + } + + public static DataTemplate ScrollToItemTemplate() + { + return new DataTemplate(() => + { + var templateLayout = new Grid + { + BackgroundColor = Color.Bisque, + + RowDefinitions = new RowDefinitionCollection { new RowDefinition(), new RowDefinition {Height = GridLength.Auto} }, + WidthRequest = 100, + HeightRequest = 140 + }; + + var image = new Image + { + Margin = new Thickness(5), + HeightRequest = 100, + WidthRequest = 100, + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center, + Aspect = Aspect.AspectFit + }; + + image.SetBinding(Image.SourceProperty, new Binding("Image")); + + var caption = new Label + { + HorizontalOptions = LayoutOptions.Fill, + HorizontalTextAlignment = TextAlignment.Center, + HeightRequest = 40, WidthRequest = 100, + BackgroundColor = Color.Crimson, + Text = "Caption" + }; + + caption.SetBinding(Label.TextProperty, new Binding("Date", stringFormat: "{0:d}")); + + templateLayout.Children.Add(image); + templateLayout.Children.Add(caption); + + Grid.SetRow(caption, 1); + + return templateLayout; + }); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml new file mode 100644 index 0000000..79e7a8c --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml.cs new file mode 100644 index 0000000..82bad51 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/FilterCollectionView.xaml.cs @@ -0,0 +1,54 @@ +using Xamarin.Forms.Xaml; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class FilterCollectionView : ContentPage + { + readonly DemoFilteredItemSource _demoFilteredItemSource = new DemoFilteredItemSource(); + + public FilterCollectionView () + { + InitializeComponent (); + + CollectionView.ItemTemplate = ExampleTemplates.PhotoTemplate(); + + CollectionView.ItemsSource = _demoFilteredItemSource.Items; + + SearchBar.TextChanged += SearchBarOnTextChanged; + UseEmptyView.Toggled += UseEmptyViewOnToggled; + + UpdateEmptyView(); + } + + void UseEmptyViewOnToggled(object sender, ToggledEventArgs e) + { + UpdateEmptyView(); + } + + void UpdateEmptyView() + { + if (UseEmptyView.IsToggled) + { + CollectionView.EmptyView = new Label + { + Text = "Nothing to see here", + TextColor = Color.Coral, + HorizontalTextAlignment = TextAlignment.Center, + VerticalTextAlignment = TextAlignment.Center, + HorizontalOptions = LayoutOptions.Fill, + VerticalOptions = LayoutOptions.Fill + }; + } + else + { + CollectionView.EmptyView = null; + } + } + + void SearchBarOnTextChanged(object sender, TextChangedEventArgs e) + { + _demoFilteredItemSource.FilterItems(e.NewTextValue); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemAdder.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemAdder.cs new file mode 100644 index 0000000..dfb4f29 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemAdder.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.ObjectModel; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ItemAdder : CollectionModifier + { + public ItemAdder(CollectionView cv) : base(cv, "Insert") + { + } + + protected override void ModifyCollection(ObservableCollection observableCollection, params int[] indexes) + { + var index = indexes[0]; + + if (index > -1 && index < observableCollection.Count) + { + var item = new CollectionViewGalleryTestItem(DateTime.Now, "Inserted", "oasis.jpg", index); + observableCollection.Insert(index, item); + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemRemover.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemRemover.cs new file mode 100644 index 0000000..6f6642f --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemRemover.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ItemRemover : CollectionModifier + { + public ItemRemover(CollectionView cv) : base(cv, "Remove") + { + } + + protected override void ModifyCollection(ObservableCollection observableCollection, params int[] indexes) + { + var index = indexes[0]; + + if (index > -1 && index < observableCollection.Count) + { + observableCollection.Remove(observableCollection[index]); + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemReplacer.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemReplacer.cs new file mode 100644 index 0000000..f061289 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemReplacer.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ItemReplacer : CollectionModifier + { + public ItemReplacer(CollectionView cv) : base(cv, "Replace") + { + } + + protected override void ModifyCollection(ObservableCollection observableCollection, params int[] indexes) + { + var index = indexes[0]; + + if (index > -1 && index < observableCollection.Count) + { + var replacement = new CollectionViewGalleryTestItem(DateTime.Now, "Replacement", "coffee.png", index); + observableCollection[index] = replacement; + } + } + } + + internal class ItemMover : CollectionModifier + { + public ItemMover(CollectionView cv) : base(cv, "Move") + { + Entry.Keyboard = Keyboard.Default; + } + + static int ParseToken(string value) + { + if (!int.TryParse(value, out int index)) + { + return -1; + } + + return index; + } + + protected override bool ParseIndexes(out int[] indexes) + { + var text = Entry.Text; + + indexes = text.Split(',').Select(v => ParseToken(v.Trim())).ToArray(); + + return indexes.Length == 2; + } + + protected override void ModifyCollection(ObservableCollection observableCollection, params int[] indexes) + { + if (indexes.Length < 2) + { + return; + } + + var index1 = indexes[0]; + var index2 = indexes[1]; + + if (index1 > -1 && index2 > -1 && index1 < observableCollection.Count && + index2 < observableCollection.Count) + { + observableCollection.Move(index1, index2); + } + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemsSourceGenerator.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemsSourceGenerator.cs new file mode 100644 index 0000000..b1f004b --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ItemsSourceGenerator.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + [Preserve(AllMembers = true)] + public class CollectionViewGalleryTestItem + { + public DateTime Date { get; set; } + public string Caption { get; set; } + public string Image { get; set; } + public int Index { get; set; } + + public CollectionViewGalleryTestItem(DateTime date, string caption, string image, int index) + { + Date = date; + Caption = caption; + Image = image; + Index = index; + } + + public override string ToString() + { + return $"{Date:D}"; + } + } + + internal class ItemsSourceGenerator : ContentView + { + readonly ItemsView _cv; + readonly Entry _entry; + + public ItemsSourceGenerator(ItemsView cv, int initialItems = 1000) + { + _cv = cv; + + var layout = new StackLayout + { + Orientation = StackOrientation.Horizontal, + HorizontalOptions = LayoutOptions.Fill + }; + + var button = new Button { Text = "Update" }; + var label = new Label { Text = "Item count:", VerticalTextAlignment = TextAlignment.Center }; + _entry = new Entry { Keyboard = Keyboard.Numeric, Text = initialItems.ToString(), WidthRequest = 200 }; + + layout.Children.Add(label); + layout.Children.Add(_entry); + layout.Children.Add(button); + + button.Clicked += GenerateItems; + + Content = layout; + } + + readonly string[] _images = + { + "cover1.jpg", + "oasis.jpg", + "photo.jpg", + "Vegetables.jpg", + "Fruits.jpg", + "FlowerBuds.jpg", + "Legumes.jpg" + }; + + public void GenerateItems() + { + if (int.TryParse(_entry.Text, out int count)) + { + var items = new List(); + + for (int n = 0; n < count; n++) + { + items.Add(new CollectionViewGalleryTestItem(DateTime.Now.AddDays(n), + $"{_images[n % _images.Length]}, {n}", _images[n % _images.Length], n)); + } + + _cv.ItemsSource = items; + } + } + + public void GenerateObservableCollection() + { + if (int.TryParse(_entry.Text, out int count)) + { + var items = new List(); + + for (int n = 0; n < count; n++) + { + items.Add(new CollectionViewGalleryTestItem(DateTime.Now.AddDays(n), + $"{_images[n % _images.Length]}, {n}", _images[n % _images.Length], n)); + } + + _cv.ItemsSource = new ObservableCollection(items); + } + } + + void GenerateItems(object sender, EventArgs e) + { + GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCodeCollectionViewGridGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCodeCollectionViewGridGallery.cs new file mode 100644 index 0000000..0dbbbb9 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCodeCollectionViewGridGallery.cs @@ -0,0 +1,58 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ObservableCodeCollectionViewGallery : ContentPage + { + public ObservableCodeCollectionViewGallery(ItemsLayoutOrientation orientation = ItemsLayoutOrientation.Vertical, + bool grid = true) + { + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + IItemsLayout itemsLayout = grid + ? new GridItemsLayout(3, orientation) + : new ListItemsLayout(orientation) as IItemsLayout; + + var itemTemplate = ExampleTemplates.PhotoTemplate(); + + var collectionView = new CollectionView {ItemsLayout = itemsLayout, ItemTemplate = itemTemplate}; + + var generator = new ItemsSourceGenerator(collectionView); + + var remover = new ItemRemover(collectionView); + var adder = new ItemAdder(collectionView); + var replacer = new ItemReplacer(collectionView); + var mover = new ItemMover(collectionView); + + layout.Children.Add(generator); + + layout.Children.Add(remover); + Grid.SetRow(remover, 1); + + layout.Children.Add(adder); + Grid.SetRow(adder, 2); + + layout.Children.Add(replacer); + Grid.SetRow(replacer, 3); + + layout.Children.Add(mover); + Grid.SetRow(mover, 4); + + layout.Children.Add(collectionView); + Grid.SetRow(collectionView, 5); + + Content = layout; + + generator.GenerateObservableCollection(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCollectionGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCollectionGallery.cs new file mode 100644 index 0000000..8b9a235 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ObservableCollectionGallery.cs @@ -0,0 +1,33 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ObservableCollectionGallery : ContentPage + { + public ObservableCollectionGallery() + { + var desc = "Observable Collection Galleries"; + + var descriptionLabel = new Label { Text = desc, Margin = new Thickness(2, 2, 2, 2) }; + + Title = "Simple DataTemplate Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + + GalleryBuilder.NavButton("Filter Items", () => new FilterCollectionView(), Navigation), + + GalleryBuilder.NavButton("Add/Remove Items (list)", () => + new ObservableCodeCollectionViewGallery(grid: false), Navigation), + + GalleryBuilder.NavButton("Add/Remove Items (grid)", () => + new ObservableCodeCollectionViewGallery(), Navigation) + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToCodeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToCodeGallery.cs new file mode 100644 index 0000000..c8dd9f5 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToCodeGallery.cs @@ -0,0 +1,54 @@ +using System; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ScrollToCodeGallery : ContentPage + { + public ScrollToCodeGallery(IItemsLayout itemsLayout, ScrollToMode mode = ScrollToMode.Position, Func dataTemplate = null) + { + Title = $"ScrollTo (Code, {itemsLayout})"; + + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var itemTemplate = dataTemplate == null ? ExampleTemplates.ScrollToIndexTemplate() : dataTemplate(); + + var collectionView = new CollectionView + { + ItemsLayout = itemsLayout, + ItemTemplate = itemTemplate, + }; + + var generator = new ItemsSourceGenerator(collectionView, initialItems: 50); + layout.Children.Add(generator); + + if (mode == ScrollToMode.Position) + { + var scrollToControl = new ScrollToIndexControl(collectionView); + layout.Children.Add(scrollToControl); + Grid.SetRow(scrollToControl, 1); + } + else + { + var scrollToControl = new ScrollToItemControl(collectionView); + layout.Children.Add(scrollToControl); + Grid.SetRow(scrollToControl, 1); + } + + layout.Children.Add(collectionView); + + Grid.SetRow(collectionView, 2); + + Content = layout; + + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToGallery.cs new file mode 100644 index 0000000..017481e --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToGallery.cs @@ -0,0 +1,47 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ScrollToGallery : ContentPage + { + public ScrollToGallery() + { + var descriptionLabel = + new Label { Text = "ScrollTo Galleries", Margin = new Thickness(2, 2, 2, 2) }; + + Title = "ScrollTo Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + GalleryBuilder.NavButton("ScrollTo Index (Code, Horizontal List)", () => + new ScrollToCodeGallery(ListItemsLayout.HorizontalList), Navigation), + GalleryBuilder.NavButton("ScrollTo Index (Code, Vertical List)", () => + new ScrollToCodeGallery(ListItemsLayout.VerticalList), Navigation), + GalleryBuilder.NavButton("ScrollTo Index (Code, Horizontal Grid)", () => + new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Horizontal)), + Navigation), + GalleryBuilder.NavButton("ScrollTo Index (Code, Vertical Grid)", () => + new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Vertical)), + Navigation), + + GalleryBuilder.NavButton("ScrollTo Item (Code, Horizontal List)", () => + new ScrollToCodeGallery(ListItemsLayout.HorizontalList, ScrollToMode.Element, + ExampleTemplates.ScrollToItemTemplate), Navigation), + GalleryBuilder.NavButton("ScrollTo Item (Code, Vertical List)", () => + new ScrollToCodeGallery(ListItemsLayout.VerticalList, ScrollToMode.Element, + ExampleTemplates.ScrollToItemTemplate), Navigation), + GalleryBuilder.NavButton("ScrollTo Item (Code, Horizontal Grid)", () => + new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Horizontal), + ScrollToMode.Element, ExampleTemplates.ScrollToItemTemplate), Navigation), + GalleryBuilder.NavButton("ScrollTo Item (Code, Vertical Grid)", () => + new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Vertical), + ScrollToMode.Element, ExampleTemplates.ScrollToItemTemplate), Navigation) + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToIndexControl.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToIndexControl.cs new file mode 100644 index 0000000..d8a83b0 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToIndexControl.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ScrollToIndexControl : ContentView + { + readonly Entry _entry; + readonly Switch _animateSwitch; + readonly Label _currentIndex; + ScrollToPosition _currentScrollToPosition; + readonly ItemsView _itemsView; + int _index; + + public ScrollToIndexControl(ItemsView itemsView, bool showPositionSelector = true) + { + _itemsView = itemsView; + + var layout = new StackLayout { Margin = 3 }; + + var indexLabel = new Label { Text = "Scroll To Index: ", VerticalTextAlignment = TextAlignment.Center}; + _entry = new Entry { Keyboard = Keyboard.Numeric, Text = "0", WidthRequest = 200 }; + var indexButton = new Button { Text = "Go" }; + + indexButton.Clicked += ScrollTo; + + var row1 = new StackLayout { Orientation = StackOrientation.Horizontal }; + row1.Children.Add(indexLabel); + row1.Children.Add(_entry); + row1.Children.Add(indexButton); + + layout.Children.Add(row1); + + var animateLabel = new Label { Text = "Animate: ", VerticalTextAlignment = TextAlignment.Center}; + _animateSwitch = new Switch { IsToggled = true }; + + var row2 = new StackLayout { Orientation = StackOrientation.Horizontal }; + row2.Children.Add(animateLabel); + row2.Children.Add(_animateSwitch); + + _currentIndex = new Label + { + Text = _index.ToString(), + WidthRequest = 100, + VerticalTextAlignment = TextAlignment.Center, + HorizontalTextAlignment = TextAlignment.Center + }; + + var forwardButton = new Button { Text = "Advance 1 >>"}; + forwardButton.Clicked += (sender, args) => + { + _index = _index + 1; + _currentIndex.Text = _index.ToString(); + ScrollToIndex(_index); + }; + + var backButton = new Button { Text = "<< Back 1"}; + backButton.Clicked += (sender, args) => + { + if (_index > 0) + { + _index = _index - 1; + _currentIndex.Text = _index.ToString(); + ScrollToIndex(_index); + } + }; + + layout.Children.Add(row2); + + var row3 = new StackLayout { Orientation = StackOrientation.Horizontal }; + row3.Children.Add(backButton); + row3.Children.Add(_currentIndex); + row3.Children.Add(forwardButton); + + layout.Children.Add(row3); + + if (showPositionSelector) + { + var row4 = new StackLayout { Orientation = StackOrientation.Horizontal }; + var scrollPositionSelector = new EnumSelector(() => _currentScrollToPosition, + type => _currentScrollToPosition = type); + row4.Children.Add(scrollPositionSelector); + + layout.Children.Add(row4); + } + + Content = layout; + } + + void ScrollToIndex(int index) + { + _itemsView.ScrollTo(index, position: _currentScrollToPosition, animate: _animateSwitch.IsToggled); + } + + void ScrollTo() + { + if (int.TryParse(_entry.Text, out int index)) + { + ScrollToIndex(index); + _index = index; + _currentIndex.Text = _index.ToString(); + } + } + + void ScrollTo(object sender, EventArgs e) + { + ScrollTo(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToItemControl.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToItemControl.cs new file mode 100644 index 0000000..adcbd5a --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/ScrollToItemControl.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class ScrollToItemControl : ContentView + { + readonly Picker _picker; + ItemsView _itemsView; + ScrollToPosition _currentScrollToPosition; + Switch _animateSwitch; + + public ScrollToItemControl(ItemsView itemsView, bool showPositionSelector = true) + { + _itemsView = itemsView; + + var layout = new StackLayout { Margin = 3 }; + + _itemsView.PropertyChanged += (sender, args) => + { + if (args.PropertyName == ItemsView.ItemsSourceProperty.PropertyName) + { + var items = new List(); + foreach (var item in itemsView.ItemsSource) + { + items.Add(item); + } + + _picker.ItemsSource = items; + } + }; + + var indexLabel = new Label { Text = "Scroll To Item: ", VerticalTextAlignment = TextAlignment.Center}; + _picker = new Picker{ WidthRequest = 200 }; + var indexButton = new Button { Text = "Go" }; + + indexButton.Clicked += ScrollTo; + + var row1 = new StackLayout { Orientation = StackOrientation.Horizontal }; + row1.Children.Add(indexLabel); + row1.Children.Add(_picker); + row1.Children.Add(indexButton); + + layout.Children.Add(row1); + + var animateLabel = new Label { Text = "Animate: ", VerticalTextAlignment = TextAlignment.Center}; + _animateSwitch = new Switch { IsToggled = true }; + + var row2 = new StackLayout { Orientation = StackOrientation.Horizontal }; + row2.Children.Add(animateLabel); + row2.Children.Add(_animateSwitch); + + layout.Children.Add(row2); + + if (showPositionSelector) + { + var row4 = new StackLayout { Orientation = StackOrientation.Horizontal }; + + var scrollPositionSelector = new EnumSelector(() => _currentScrollToPosition, + type => _currentScrollToPosition = type); + row4.Children.Add(scrollPositionSelector); + + layout.Children.Add(row4); + } + + Content = layout; + } + + void ScrollToItem(object item) + { + _itemsView.ScrollTo(item, position: _currentScrollToPosition, animate: _animateSwitch.IsToggled); + } + + void ScrollTo() + { + if (_picker.SelectedItem != null) + { + ScrollToItem(_picker.SelectedItem ); + } + } + + void ScrollTo(object sender, EventArgs e) + { + ScrollTo(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsCodeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsCodeGallery.cs new file mode 100644 index 0000000..4a50799 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsCodeGallery.cs @@ -0,0 +1,59 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class SnapPointsCodeGallery : ContentPage + { + public SnapPointsCodeGallery(ItemsLayout itemsLayout) + { + Title = $"Snap Points (Code, {itemsLayout})"; + + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + itemsLayout.SnapPointsAlignment = SnapPointsAlignment.Start; + itemsLayout.SnapPointsType = SnapPointsType.None; + + var itemTemplate = ExampleTemplates.SnapPointsTemplate(); + + var collectionView = new CollectionView + { + ItemsLayout = itemsLayout, + ItemTemplate = itemTemplate, + }; + + var generator = new ItemsSourceGenerator(collectionView, initialItems: 50); + + var snapPointsTypeSelector = new EnumSelector(() => itemsLayout.SnapPointsType, + type => itemsLayout.SnapPointsType = type); + + var snapPointsAlignmentSelector = new EnumSelector(() => itemsLayout.SnapPointsAlignment, + type => itemsLayout.SnapPointsAlignment = type); + + var flowDirectionSelector = new EnumSelector(() => layout.FlowDirection, + type => layout.FlowDirection = type); + + layout.Children.Add(generator); + layout.Children.Add(snapPointsTypeSelector); + layout.Children.Add(snapPointsAlignmentSelector); + layout.Children.Add(flowDirectionSelector); + layout.Children.Add(collectionView); + + Grid.SetRow(snapPointsTypeSelector, 1); + Grid.SetRow(snapPointsAlignmentSelector, 2); + Grid.SetRow(flowDirectionSelector, 3); + Grid.SetRow(collectionView, 4); + + Content = layout; + + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsGallery.cs new file mode 100644 index 0000000..907b7de --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SnapPointsGallery.cs @@ -0,0 +1,34 @@ +using System; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class SnapPointsGallery : ContentPage + { + public SnapPointsGallery() + { + var descriptionLabel = + new Label { Text = "Snap Points Galleries", Margin = new Thickness(2, 2, 2, 2) }; + + Title = "Snap Points Galleries"; + + Content = new ScrollView + { + Content = new StackLayout + { + Children = + { + descriptionLabel, + GalleryBuilder.NavButton("Snap Points (Code, Horizontal List)", () => + new SnapPointsCodeGallery(ListItemsLayout.HorizontalList as ItemsLayout), Navigation), + GalleryBuilder.NavButton("Snap Points (Code, Vertical List)", () => + new SnapPointsCodeGallery(ListItemsLayout.VerticalList as ItemsLayout), Navigation), + GalleryBuilder.NavButton("Snap Points (Code, Horizontal Grid)", () => + new SnapPointsCodeGallery(new GridItemsLayout(2, ItemsLayoutOrientation.Horizontal)), Navigation), + GalleryBuilder.NavButton("Snap Points (Code, Vertical Grid)", () => + new SnapPointsCodeGallery(new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)), Navigation), + } + } + }; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SpanSetter.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SpanSetter.cs new file mode 100644 index 0000000..3c0c677 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/SpanSetter.cs @@ -0,0 +1,49 @@ +using System; + +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class SpanSetter : ContentView + { + readonly CollectionView _cv; + readonly Entry _entry; + + public SpanSetter(CollectionView cv) + { + _cv = cv; + + var layout = new StackLayout + { + Orientation = StackOrientation.Horizontal, + HorizontalOptions = LayoutOptions.Fill + }; + + var button = new Button { Text = "Update" }; + var label = new Label { Text = "Span:", VerticalTextAlignment = TextAlignment.Center }; + _entry = new Entry { Keyboard = Keyboard.Numeric, Text = "3", WidthRequest = 200 }; + + layout.Children.Add(label); + layout.Children.Add(_entry); + layout.Children.Add(button); + + button.Clicked += UpdateSpan ; + + Content = layout; + } + + public void UpdateSpan() + { + if (int.TryParse(_entry.Text, out int span)) + { + if (_cv.ItemsLayout is GridItemsLayout gridItemsLayout) + { + gridItemsLayout.Span = span; + } + } + } + + public void UpdateSpan(object sender, EventArgs e) + { + UpdateSpan(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGallery.cs new file mode 100644 index 0000000..cb01f08 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGallery.cs @@ -0,0 +1,36 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class TemplateCodeCollectionViewGallery : ContentPage + { + public TemplateCodeCollectionViewGallery(IItemsLayout itemsLayout) + { + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var itemTemplate = ExampleTemplates.PhotoTemplate(); + + var collectionView = new CollectionView + { + ItemsLayout = itemsLayout, + ItemTemplate = itemTemplate + }; + + var generator = new ItemsSourceGenerator(collectionView, initialItems: 20); + + layout.Children.Add(generator); + layout.Children.Add(collectionView); + + Grid.SetRow(collectionView, 1); + + Content = layout; + + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGridGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGridGallery.cs new file mode 100644 index 0000000..9367cd3 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TemplateCodeCollectionViewGridGallery.cs @@ -0,0 +1,38 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class TemplateCodeCollectionViewGridGallery : ContentPage + { + public TemplateCodeCollectionViewGridGallery(ItemsLayoutOrientation orientation = ItemsLayoutOrientation.Vertical) + { + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var itemsLayout = new GridItemsLayout(2, orientation); + + var itemTemplate = ExampleTemplates.PhotoTemplate(); + + var collectionView = new CollectionView {ItemsLayout = itemsLayout, ItemTemplate = itemTemplate}; + + var generator = new ItemsSourceGenerator(collectionView, 100); + var spanSetter = new SpanSetter(collectionView); + + layout.Children.Add(generator); + layout.Children.Add(spanSetter); + Grid.SetRow(spanSetter, 1); + layout.Children.Add(collectionView); + Grid.SetRow(collectionView, 2); + + Content = layout; + + spanSetter.UpdateSpan(); + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGallery.cs new file mode 100644 index 0000000..6326501 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGallery.cs @@ -0,0 +1,32 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class TextCodeCollectionViewGallery : ContentPage + { + public TextCodeCollectionViewGallery(IItemsLayout itemsLayout) + { + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var collectionView = new CollectionView + { + ItemsLayout = itemsLayout + }; + + var generator = new ItemsSourceGenerator(collectionView); + + layout.Children.Add(generator); + layout.Children.Add(collectionView); + Grid.SetRow(collectionView, 1); + + Content = layout; + + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGridGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGridGallery.cs new file mode 100644 index 0000000..4249080 --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/TextCodeCollectionViewGridGallery.cs @@ -0,0 +1,36 @@ +namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries +{ + internal class TextCodeCollectionViewGridGallery : ContentPage + { + public TextCodeCollectionViewGridGallery(ItemsLayoutOrientation orientation = ItemsLayoutOrientation.Vertical) + { + var layout = new Grid + { + RowDefinitions = new RowDefinitionCollection + { + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Auto }, + new RowDefinition { Height = GridLength.Star } + } + }; + + var itemsLayout = new GridItemsLayout(2, orientation); + + var collectionView = new CollectionView {ItemsLayout = itemsLayout}; + + var generator = new ItemsSourceGenerator(collectionView); + var spanSetter = new SpanSetter(collectionView); + + layout.Children.Add(generator); + layout.Children.Add(spanSetter); + Grid.SetRow(spanSetter, 1); + layout.Children.Add(collectionView); + Grid.SetRow(collectionView, 2); + + Content = layout; + + spanSetter.UpdateSpan(); + generator.GenerateItems(); + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/GalleryBuilder.cs b/Xamarin.Forms.Controls/GalleryPages/GalleryBuilder.cs new file mode 100644 index 0000000..57719da --- /dev/null +++ b/Xamarin.Forms.Controls/GalleryPages/GalleryBuilder.cs @@ -0,0 +1,14 @@ +using System; + +namespace Xamarin.Forms.Controls.GalleryPages +{ + public static class GalleryBuilder + { + public static Button NavButton(string galleryName, Func gallery, INavigation nav) + { + var button = new Button { Text = $"{galleryName}" }; + button.Clicked += (sender, args) => { nav.PushAsync(gallery()); }; + return button; + } + } +} \ No newline at end of file diff --git a/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/DisabledStatesGallery.cs b/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/DisabledStatesGallery.cs index 8acfaeb..b8ed9cb 100644 --- a/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/DisabledStatesGallery.cs +++ b/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/DisabledStatesGallery.cs @@ -4,13 +4,6 @@ namespace Xamarin.Forms.Controls.GalleryPages.VisualStateManagerGalleries { public class DisabledStatesGallery : ContentPage { - static Button GalleryNav(string control, Func gallery, INavigation nav) - { - var button = new Button { Text = $"{control} Disabled States" }; - button.Clicked += (sender, args) => { nav.PushAsync(gallery()); }; - return button; - } - public DisabledStatesGallery() { var desc = "Some of the XF controls have legacy (pre-VSM) behaviors such that when IsEnabled is set to `false`, they " @@ -32,13 +25,13 @@ namespace Xamarin.Forms.Controls.GalleryPages.VisualStateManagerGalleries Children = { descriptionLabel, - GalleryNav("Editor", () => new EditorDisabledStatesGallery(), Navigation), - GalleryNav("SearchBar", () => new SearchBarDisabledStatesGallery(), Navigation), - GalleryNav("Entry", () => new EntryDisabledStatesGallery(), Navigation), - GalleryNav("Button", () => new ButtonDisabledStatesGallery(), Navigation), - GalleryNav("Picker", () => new PickerDisabledStatesGallery(), Navigation), - GalleryNav("TimePicker", () => new TimePickerDisabledStatesGallery(), Navigation), - GalleryNav("DatePicker", () => new DatePickerDisabledStatesGallery(), Navigation) + GalleryBuilder.NavButton("Editor Disabled States", () => new EditorDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("SearchBar Disabled States", () => new SearchBarDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("Entry Disabled States", () => new EntryDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("Button Disabled States", () => new ButtonDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("Picker Disabled States", () => new PickerDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("TimePicker Disabled States", () => new TimePickerDisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("DatePicker Disabled States", () => new DatePickerDisabledStatesGallery(), Navigation) } } }; diff --git a/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/VisualStateManagerGallery.cs b/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/VisualStateManagerGallery.cs index aa5d6fc..087466e 100644 --- a/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/VisualStateManagerGallery.cs +++ b/Xamarin.Forms.Controls/GalleryPages/VisualStateManagerGalleries/VisualStateManagerGallery.cs @@ -4,25 +4,18 @@ namespace Xamarin.Forms.Controls.GalleryPages.VisualStateManagerGalleries { public class VisualStateManagerGallery : ContentPage { - static Button GalleryNav(string galleryName, Func gallery, INavigation nav) - { - var button = new Button { Text = $"{galleryName}" }; - button.Clicked += (sender, args) => { nav.PushAsync(gallery()); }; - return button; - } - public VisualStateManagerGallery() { Content = new StackLayout { Children = { - GalleryNav("Disabled States Gallery", () => new DisabledStatesGallery(), Navigation), - GalleryNav("OnPlatform Example", () => new OnPlatformExample(), Navigation), - GalleryNav("OnIdiom Example", () => new OnIdiomExample(), Navigation), - GalleryNav("Validation Example", () => new ValidationExample(), Navigation), - GalleryNav("Code (No XAML) Example", () => new CodeOnlyExample(), Navigation), - GalleryNav("VisualStates directly on Elements", () => new VisualStatesDirectlyOnElements(), Navigation) + GalleryBuilder.NavButton("Disabled States Gallery", () => new DisabledStatesGallery(), Navigation), + GalleryBuilder.NavButton("OnPlatform Example", () => new OnPlatformExample(), Navigation), + GalleryBuilder.NavButton("OnIdiom Example", () => new OnIdiomExample(), Navigation), + GalleryBuilder.NavButton("Validation Example", () => new ValidationExample(), Navigation), + GalleryBuilder.NavButton("Code (No XAML) Example", () => new CodeOnlyExample(), Navigation), + GalleryBuilder.NavButton("VisualStates directly on Elements", () => new VisualStatesDirectlyOnElements(), Navigation) } }; } diff --git a/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj b/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj index 34aff01..95da9ac 100644 --- a/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj +++ b/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj @@ -47,13 +47,87 @@ - - BindableLayoutGalleryPage.xaml - - - OnPlatformExample.xaml - + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + diff --git a/Xamarin.Forms.Core.Design/toolbox/Xamarin.Forms.toolbox.xml b/Xamarin.Forms.Core.Design/toolbox/Xamarin.Forms.toolbox.xml index e06ebaf..2c3ecff 100644 --- a/Xamarin.Forms.Core.Design/toolbox/Xamarin.Forms.toolbox.xml +++ b/Xamarin.Forms.Core.Design/toolbox/Xamarin.Forms.toolbox.xml @@ -17,6 +17,29 @@