Basic Header/Footer for UWP CollectionView (#7237)
authorE.Z. Hart <hartez@users.noreply.github.com>
Thu, 22 Aug 2019 11:10:12 +0000 (05:10 -0600)
committerRui Marinho <me@ruimarinho.net>
Thu, 22 Aug 2019 11:10:12 +0000 (12:10 +0100)
Xamarin.Forms.Platform.UAP/CollectionView/ItemsViewRenderer.cs
Xamarin.Forms.Platform.UAP/CollectionView/SelectableItemsViewRenderer.cs

index e8480a3..a1e9d5a 100644 (file)
@@ -12,10 +12,12 @@ using Windows.UI.Xaml.Data;
 using Xamarin.Forms.Internals;
 using Xamarin.Forms.Platform.UAP;
 using UwpScrollBarVisibility = Windows.UI.Xaml.Controls.ScrollBarVisibility;
+using UWPApp = Windows.UI.Xaml.Application;
+using UWPDataTemplate = Windows.UI.Xaml.DataTemplate;
 
 namespace Xamarin.Forms.Platform.UWP
 {
-       public class ItemsViewRenderer : ViewRenderer<CollectionView, ListViewBase>
+       public class ItemsViewRenderer : ViewRenderer<ItemsView, ListViewBase>
        {
                IItemsLayout _layout;
                CollectionViewSource _collectionViewSource;
@@ -24,9 +26,15 @@ namespace Xamarin.Forms.Platform.UWP
                UwpScrollBarVisibility? _defaultHorizontalScrollVisibility;
                UwpScrollBarVisibility? _defaultVerticalScrollVisibility;
 
+               UWPDataTemplate ViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["View"];
+               UWPDataTemplate ItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["ItemsViewDefaultTemplate"];
+
+               View _currentHeader;
+               View _currentFooter;
+
                protected ItemsControl ItemsControl { get; private set; }
 
-               protected override void OnElementChanged(ElementChangedEventArgs<CollectionView> args)
+               protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> args)
                {
                        base.OnElementChanged(args);
                        TearDownOldElement(args.OldElement);
@@ -53,6 +61,14 @@ namespace Xamarin.Forms.Platform.UWP
                        {
                                UpdateVerticalScrollBarVisibility();
                        }
+                       else if (changedProperty.IsOneOf(ItemsView.HeaderProperty, ItemsView.HeaderTemplateProperty))
+                       {
+                               UpdateHeader();
+                       }
+                       else if (changedProperty.IsOneOf(ItemsView.FooterProperty, ItemsView.FooterTemplateProperty))
+                       {
+                               UpdateFooter();
+                       }
                }
 
                protected virtual ListViewBase SelectLayout(IItemsLayout layoutSpecification)
@@ -133,8 +149,7 @@ namespace Xamarin.Forms.Platform.UWP
                        // TODO hartez 2018/06/23 13:47:27 Handle DataTemplateSelector case
                        // Actually, DataTemplateExtensions CreateContent might handle the selector for us
 
-                       ListViewBase.ItemTemplate =
-                               (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["ItemsViewDefaultTemplate"];
+                       ListViewBase.ItemTemplate = ItemsViewTemplate;
 
                        if (itemsControlItemTemplate == null)
                        {
@@ -143,6 +158,104 @@ namespace Xamarin.Forms.Platform.UWP
                        }
                }
 
+               protected virtual void UpdateHeader()
+               {
+                       if (ListViewBase == null)
+                       {
+                               return;
+                       }
+
+                       if (_currentHeader != null)
+                       {
+                               Element.RemoveLogicalChild(_currentHeader);
+                               _currentHeader = null;
+                       }
+
+                       var header = Element.Header;
+
+                       switch (header)
+                       {
+                               case null:
+                                       ListViewBase.Header = null;
+                                       break;
+
+                               case string text:
+                                       ListViewBase.HeaderTemplate = null;
+                                       ListViewBase.Header = new TextBlock { Text = text };
+                                       break;
+
+                               case View view:
+                                       ListViewBase.HeaderTemplate = ViewTemplate;
+                                       _currentHeader = view;
+                                       Element.AddLogicalChild(_currentHeader);
+                                       ListViewBase.Header = view;
+                                       break;
+
+                               default:
+                                       var headerTemplate = Element.HeaderTemplate;
+                                       if (headerTemplate != null)
+                                       {
+                                               ListViewBase.HeaderTemplate = ItemsViewTemplate;
+                                               ListViewBase.Header = new ItemTemplateContext(headerTemplate, header, Element);
+                                       }
+                                       else
+                                       {
+                                               ListViewBase.HeaderTemplate = null;
+                                               ListViewBase.Header = null;
+                                       }
+                                       break;
+                       }
+               }
+
+               protected virtual void UpdateFooter()
+               {
+                       if (ListViewBase == null)
+                       {
+                               return;
+                       }
+
+                       if (_currentFooter != null)
+                       {
+                               Element.RemoveLogicalChild(_currentFooter);
+                               _currentFooter = null;
+                       }
+
+                       var footer = Element.Footer;
+
+                       switch (footer)
+                       {
+                               case null:
+                                       ListViewBase.Footer = null;
+                                       break;
+
+                               case string text:
+                                       ListViewBase.FooterTemplate = null;
+                                       ListViewBase.Footer = new TextBlock { Text = text };
+                                       break;
+
+                               case View view:
+                                       ListViewBase.FooterTemplate = ViewTemplate;
+                                       _currentFooter = view;
+                                       Element.AddLogicalChild(_currentFooter);
+                                       ListViewBase.Footer = view;
+                                       break;
+
+                               default:
+                                       var footerTemplate = Element.FooterTemplate;
+                                       if (footerTemplate != null)
+                                       {
+                                               ListViewBase.FooterTemplate = ItemsViewTemplate;
+                                               ListViewBase.Footer = new ItemTemplateContext(footerTemplate, footer, Element);
+                                       }
+                                       else
+                                       {
+                                               ListViewBase.FooterTemplate = null;
+                                               ListViewBase.Footer = null;
+                                       }
+                                       break;
+                       }
+               }
+
                static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout)
                {
                        var gridView = new FormsGridView();
@@ -213,6 +326,8 @@ namespace Xamarin.Forms.Platform.UWP
 
                        UpdateItemTemplate();
                        UpdateItemsSource();
+                       UpdateHeader();
+                       UpdateFooter();
                        UpdateVerticalScrollBarVisibility();
                        UpdateHorizontalScrollBarVisibility();
 
@@ -425,5 +540,9 @@ namespace Xamarin.Forms.Platform.UWP
                                await JumpTo(list, targetItem, args.ScrollToPosition);
                        }
                }
+
+               
+
+               
        }
 }
\ No newline at end of file
index afd6ea9..132f5a0 100644 (file)
@@ -121,7 +121,7 @@ namespace Xamarin.Forms.Platform.UWP
 
                void OnNativeSelectionChanged(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
                {
-                       if (Element != null)
+                       if (Element is SelectableItemsView selectableItemsView)
                        {
                                switch (ListViewBase.SelectionMode)
                                {
@@ -130,12 +130,12 @@ namespace Xamarin.Forms.Platform.UWP
                                        case UWPListViewSelectionMode.Single:
                                                var selectedItem = 
                                                        ListViewBase.SelectedItem is ItemTemplateContext itemPair ? itemPair.Item : ListViewBase.SelectedItem;
-                                               Element.SelectionChanged -= OnSelectionChanged;
-                                               Element.SetValueFromRenderer(SelectableItemsView.SelectedItemProperty, selectedItem);
-                                               Element.SelectionChanged += OnSelectionChanged;
+                                               selectableItemsView.SelectionChanged -= OnSelectionChanged;
+                                               selectableItemsView.SetValueFromRenderer(SelectableItemsView.SelectedItemProperty, selectedItem);
+                                               selectableItemsView.SelectionChanged += OnSelectionChanged;
                                                break;
                                        case UWPListViewSelectionMode.Multiple:
-                                               Element.SelectionChanged -= OnSelectionChanged;
+                                               selectableItemsView.SelectionChanged -= OnSelectionChanged;
 
                                                _selectableItemsView.SelectedItems.Clear();
                                                var selectedItems =
@@ -152,7 +152,7 @@ namespace Xamarin.Forms.Platform.UWP
                                                        _selectableItemsView.SelectedItems.Add(item);
                                                }
 
-                                               Element.SelectionChanged += OnSelectionChanged;
+                                               selectableItemsView.SelectionChanged += OnSelectionChanged;
                                                break;
 
                                        case UWPListViewSelectionMode.Extended: