Skip to content

Commit

Permalink
Implement EmptyView on UWP (xamarin#7438)
Browse files Browse the repository at this point in the history
  • Loading branch information
hartez authored and jfversluis committed Sep 16, 2019
1 parent 2f9aff8 commit 8b34607
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 10 deletions.
45 changes: 40 additions & 5 deletions Xamarin.Forms.Platform.UAP/CollectionView/FormsGridView.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using Windows.UI.Xaml;
using System;
using System.Globalization;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms.Platform.UWP;

namespace Xamarin.Forms.Platform.UAP
namespace Xamarin.Forms.Platform.UWP
{
// TODO hartez 2018/06/06 10:01:48 Consider whether this should be internal; it might be that we just want to make the ItemsPanel resources configurable in CollectionViewRenderer
internal class FormsGridView : GridView
internal class FormsGridView : GridView, IEmptyView
{
int _maximumRowsOrColumns;
ItemsWrapGrid _wrapGrid;
ContentControl _emptyViewContentControl;
FrameworkElement _emptyView;

public FormsGridView()
{
Expand All @@ -30,14 +33,24 @@ public int MaximumRowsOrColumns
}
}

public Visibility EmptyViewVisibility
{
get { return (Visibility)GetValue(EmptyViewVisibilityProperty); }
set { SetValue(EmptyViewVisibilityProperty, value); }
}

public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility),
typeof(FormsGridView), new PropertyMetadata(Visibility.Collapsed));

// TODO hartez 2018/06/06 10:01:32 Probably should just create a local enum for this?
public void UseHorizontalItemsPanel()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["HorizontalGridItemsPanel"];
}

public void UseVerticalalItemsPanel()
public void UseVerticalItemsPanel()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["VerticalGridItemsPanel"];
Expand All @@ -64,5 +77,27 @@ void OnLoaded(object sender, RoutedEventArgs e)
{
FindItemsWrapGrid();
}

public void SetEmptyView(FrameworkElement emptyView)
{
_emptyView = emptyView;

if (_emptyViewContentControl != null)
{
_emptyViewContentControl.Content = emptyView;
}
}

protected override void OnApplyTemplate()
{
base.OnApplyTemplate();

_emptyViewContentControl = GetTemplateChild("EmptyViewContentControl") as ContentControl;

if (_emptyView != null)
{
_emptyViewContentControl.Content = _emptyView;
}
}
}
}
42 changes: 42 additions & 0 deletions Xamarin.Forms.Platform.UAP/CollectionView/FormsListView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Xamarin.Forms.Platform.UWP
{
internal class FormsListView : Windows.UI.Xaml.Controls.ListView, IEmptyView
{
ContentControl _emptyViewContentControl;
FrameworkElement _emptyView;

public Visibility EmptyViewVisibility
{
get { return (Visibility)GetValue(EmptyViewVisibilityProperty); }
set { SetValue(EmptyViewVisibilityProperty, value); }
}

public static readonly DependencyProperty EmptyViewVisibilityProperty =
DependencyProperty.Register(nameof(EmptyViewVisibility), typeof(Visibility), typeof(FormsListView), new PropertyMetadata(Visibility.Collapsed));

public void SetEmptyView(FrameworkElement emptyView)
{
_emptyView = emptyView;

if (_emptyViewContentControl != null)
{
_emptyViewContentControl.Content = emptyView;
}
}

protected override void OnApplyTemplate()
{
base.OnApplyTemplate();

_emptyViewContentControl = GetTemplateChild("EmptyViewContentControl") as ContentControl;

if (_emptyView != null)
{
_emptyViewContentControl.Content = _emptyView;
}
}
}
}
10 changes: 10 additions & 0 deletions Xamarin.Forms.Platform.UAP/CollectionView/IEmptyView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Windows.UI.Xaml;

namespace Xamarin.Forms.Platform.UWP
{
internal interface IEmptyView
{
Visibility EmptyViewVisibility { get; set; }
void SetEmptyView(FrameworkElement emptyView);
}
}
98 changes: 97 additions & 1 deletion Xamarin.Forms.Platform.UAP/CollectionView/ItemsViewRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using UwpScrollBarVisibility = Windows.UI.Xaml.Controls.ScrollBarVisibility;
using UWPApp = Windows.UI.Xaml.Application;
using UWPDataTemplate = Windows.UI.Xaml.DataTemplate;
using System.Collections.Specialized;

namespace Xamarin.Forms.Platform.UWP
{
Expand All @@ -28,6 +29,9 @@ public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, ListViewBase>
protected UWPDataTemplate ViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["View"];
protected UWPDataTemplate ItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["ItemsViewDefaultTemplate"];

FrameworkElement _emptyView;
View _formsEmptyView;

protected ItemsControl ItemsControl { get; private set; }

protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> args)
Expand Down Expand Up @@ -57,6 +61,10 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
{
UpdateVerticalScrollBarVisibility();
}
else if (changedProperty.IsOneOf(ItemsView.EmptyViewProperty, ItemsView.EmptyViewTemplateProperty))
{
UpdateEmptyView();
}
}

protected abstract ListViewBase SelectListViewBase();
Expand All @@ -76,6 +84,11 @@ protected virtual void UpdateItemsSource()

if (itemsSource == null)
{
if (_collectionViewSource?.Source is INotifyCollectionChanged incc)
{
incc.CollectionChanged -= ItemsChanged;
}

_collectionViewSource = null;
return;
}
Expand All @@ -97,6 +110,11 @@ protected virtual void UpdateItemsSource()
Source = TemplatedItemSourceFactory.Create(itemsSource, itemTemplate, Element),
IsSourceGrouped = false
};

if (_collectionViewSource?.Source is INotifyCollectionChanged incc)
{
incc.CollectionChanged += ItemsChanged;
}
}
else
{
Expand All @@ -108,6 +126,13 @@ protected virtual void UpdateItemsSource()
}

ListViewBase.ItemsSource = _collectionViewSource.View;

UpdateEmptyViewVisibility();
}

void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateEmptyViewVisibility();
}

protected virtual void UpdateItemTemplate()
Expand Down Expand Up @@ -148,6 +173,7 @@ protected virtual void SetUpNewElement(ItemsView newElement)
UpdateItemsSource();
UpdateVerticalScrollBarVisibility();
UpdateHorizontalScrollBarVisibility();
UpdateEmptyView();

// Listen for ScrollTo requests
newElement.ScrollToRequested += ScrollToRequested;
Expand Down Expand Up @@ -357,5 +383,75 @@ protected virtual async Task ScrollTo(ScrollToRequestEventArgs args)
await JumpTo(list, targetItem, args.ScrollToPosition);
}
}

protected virtual void UpdateEmptyView()
{
if (Element == null || ListViewBase == null)
{
return;
}

var emptyView = Element.EmptyView;

if (emptyView == null)
{
return;
}

switch (emptyView)
{
case string text:
_emptyView = new TextBlock { Text = text };
break;
case View view:
_emptyView = RealizeEmptyView(view);
break;
default:
_emptyView = RealizeEmptyViewTemplate(emptyView, Element.EmptyViewTemplate);
break;
}

(ListViewBase as IEmptyView)?.SetEmptyView(_emptyView);

UpdateEmptyViewVisibility();
}

FrameworkElement RealizeEmptyViewTemplate(object bindingContext, DataTemplate emptyViewTemplate)
{
if (emptyViewTemplate == null)
{
return new TextBlock { Text = bindingContext.ToString() };
}

var template = emptyViewTemplate.SelectDataTemplate(bindingContext, null);
var view = template.CreateContent() as View;

view.BindingContext = bindingContext;
return RealizeEmptyView(view);
}

FrameworkElement RealizeEmptyView(View view)
{
_formsEmptyView = view;
return view.GetOrCreateRenderer().ContainerElement;
}

protected virtual void UpdateEmptyViewVisibility()
{
if (_emptyView != null && ListViewBase is IEmptyView emptyView)
{
emptyView.EmptyViewVisibility = (_collectionViewSource?.View?.Count ?? 0) == 0
? Visibility.Visible
: Visibility.Collapsed;

if (emptyView.EmptyViewVisibility == Visibility.Visible)
{
if (ActualWidth >= 0 && ActualHeight >= 0)
{
_formsEmptyView?.Layout(new Rectangle(0, 0, ActualWidth, ActualHeight));
}
}
}
}
}
}
}
Loading

0 comments on commit 8b34607

Please sign in to comment.