-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()
{
}
}
+ 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()
{
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["HorizontalGridItemsPanel"];
}
- public void UseVerticalalItemsPanel()
+ public void UseVerticalItemsPanel()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["VerticalGridItemsPanel"];
{
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;
+ }
+ }
}
}
\ No newline at end of file
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+using Windows.UI.Xaml;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ internal interface IEmptyView
+ {
+ Visibility EmptyViewVisibility { get; set; }
+ void SetEmptyView(FrameworkElement emptyView);
+ }
+}
\ No newline at end of file
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
{
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)
{
UpdateVerticalScrollBarVisibility();
}
+ else if (changedProperty.IsOneOf(ItemsView.EmptyViewProperty, ItemsView.EmptyViewTemplateProperty))
+ {
+ UpdateEmptyView();
+ }
}
protected abstract ListViewBase SelectListViewBase();
if (itemsSource == null)
{
+ if (_collectionViewSource?.Source is INotifyCollectionChanged incc)
+ {
+ incc.CollectionChanged -= ItemsChanged;
+ }
+
_collectionViewSource = null;
return;
}
Source = TemplatedItemSourceFactory.Create(itemsSource, itemTemplate, Element),
IsSourceGrouped = false
};
+
+ if (_collectionViewSource?.Source is INotifyCollectionChanged incc)
+ {
+ incc.CollectionChanged += ItemsChanged;
+ }
}
else
{
}
ListViewBase.ItemsSource = _collectionViewSource.View;
+
+ UpdateEmptyViewVisibility();
+ }
+
+ void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateEmptyViewVisibility();
}
protected virtual void UpdateItemTemplate()
UpdateItemsSource();
UpdateVerticalScrollBarVisibility();
UpdateHorizontalScrollBarVisibility();
+ UpdateEmptyView();
// Listen for ScrollTo requests
newElement.ScrollToRequested += ScrollToRequested;
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));
+ }
+ }
+ }
+ }
}
-}
\ No newline at end of file
+}
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Xamarin.Forms.Platform.UWP">
-
- <ItemsPanelTemplate x:Key="HorizontalListItemsPanel">
+
+ <ItemsPanelTemplate x:Key="HorizontalListItemsPanel">
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter>
</Style>
+ <Style TargetType="local:FormsListView">
+ <Setter Property="IsTabStop" Value="False" />
+ <Setter Property="TabNavigation" Value="Once" />
+ <Setter Property="IsSwipeEnabled" Value="True" />
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
+ <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
+ <Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
+ <Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
+ <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
+ <Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
+ <Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
+ <Setter Property="UseSystemFocusVisuals" Value="True" />
+ <Setter Property="ItemContainerTransitions">
+ <Setter.Value>
+ <TransitionCollection>
+ <AddDeleteThemeTransition />
+ <ContentThemeTransition />
+ <ReorderThemeTransition />
+ <EntranceThemeTransition IsStaggeringEnabled="False" />
+ </TransitionCollection>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <ItemsStackPanel Orientation="Vertical" />
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsListView">
+ <Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
+
+ <Grid>
+
+ <ContentControl x:Name="EmptyViewContentControl" Visibility="{TemplateBinding EmptyViewVisibility}"></ContentControl>
+
+ <ScrollViewer x:Name="ScrollViewer"
+ TabNavigation="{TemplateBinding TabNavigation}"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
+ IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
+ AutomationProperties.AccessibilityView="Raw">
+ <ItemsPresenter Header="{TemplateBinding Header}"
+ HeaderTemplate="{TemplateBinding HeaderTemplate}"
+ HeaderTransitions="{TemplateBinding HeaderTransitions}"
+ Footer="{TemplateBinding Footer}"
+ FooterTemplate="{TemplateBinding FooterTemplate}"
+ FooterTransitions="{TemplateBinding FooterTransitions}"
+ Padding="{TemplateBinding Padding}" />
+ </ScrollViewer>
+
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="local:FormsGridView">
+ <Setter Property="Padding" Value="0,0,0,10" />
+ <Setter Property="IsTabStop" Value="False" />
+ <Setter Property="TabNavigation" Value="Once" />
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
+ <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
+ <Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
+ <Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
+ <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="True" />
+ <Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
+ <Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
+ <Setter Property="IsSwipeEnabled" Value="True" />
+ <Setter Property="UseSystemFocusVisuals" Value="True" />
+ <Setter Property="FocusVisualMargin" Value="-2" />
+ <Setter Property="ItemContainerTransitions">
+ <Setter.Value>
+ <TransitionCollection>
+ <AddDeleteThemeTransition />
+ <ContentThemeTransition />
+ <ReorderThemeTransition />
+ <EntranceThemeTransition IsStaggeringEnabled="False" />
+ </TransitionCollection>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <ItemsWrapGrid Orientation="Horizontal" />
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsGridView">
+ <Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
+
+ <Grid>
+
+ <ContentControl x:Name="EmptyViewContentControl" Visibility="{TemplateBinding EmptyViewVisibility}"></ContentControl>
+
+ <ScrollViewer x:Name="ScrollViewer"
+ TabNavigation="{TemplateBinding TabNavigation}"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}"
+ IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
+ AutomationProperties.AccessibilityView="Raw">
+ <ItemsPresenter Header="{TemplateBinding Header}"
+ HeaderTemplate="{TemplateBinding HeaderTemplate}"
+ HeaderTransitions="{TemplateBinding HeaderTransitions}"
+ Footer="{TemplateBinding Footer}"
+ FooterTemplate="{TemplateBinding FooterTemplate}"
+ FooterTransitions="{TemplateBinding FooterTransitions}"
+ Padding="{TemplateBinding Padding}" />
+ </ScrollViewer>
+
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
</ResourceDictionary>
}
// Default to a plain old vertical ListView
- return new Windows.UI.Xaml.Controls.ListView();
+ return new FormsListView();
}
protected virtual void UpdateHeader()
}
else
{
- gridView.UseVerticalalItemsPanel();
+ gridView.UseVerticalItemsPanel();
}
gridView.MaximumRowsOrColumns = gridItemsLayout.Span;
</PropertyGroup>
<ItemGroup>
<Compile Include="AccessibilityExtensions.cs" />
+ <Compile Include="CollectionView\FormsListView.cs" />
+ <Compile Include="CollectionView\IEmptyView.cs" />
<Compile Include="CollectionView\ItemsViewRenderer.cs" />
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />