Skip to content

Instantly share code, notes, and snippets.

@ChaseFlorell
Last active August 6, 2017 23:53
Show Gist options
  • Save ChaseFlorell/803b7caa94b005eba749 to your computer and use it in GitHub Desktop.
Save ChaseFlorell/803b7caa94b005eba749 to your computer and use it in GitHub Desktop.
Xamarin.Forms GridView
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace TimeTracker.Controls
{
public class GridView : Grid
{
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create<GridView, object>(p => p.CommandParameter, null);
public static readonly BindableProperty CommandProperty = BindableProperty.Create<GridView, ICommand>(p => p.Command, null);
private int _maxColumns = 2;
private float _tileHeight = 100;
public GridView()
{
for (var i = 0; i < MaxColumns; i++)
{
ColumnDefinitions.Add(new ColumnDefinition());
}
}
public Type ItemTemplate { get; set; }
public int MaxColumns
{
get { return _maxColumns; }
set { _maxColumns = value; }
}
public float TileHeight
{
get { return _tileHeight; }
set { _tileHeight = value; }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public ICommand Command
{
get { return (ICommand) GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public async Task BuildTiles<T>(IEnumerable<T> tiles)
{
// Wipe out the previous row definitions if they're there.
if (RowDefinitions.Any())
{
RowDefinitions.Clear();
}
var enumerable = tiles as IList<T> ?? tiles.ToList();
var numberOfRows = Math.Ceiling(enumerable.Count/(float) MaxColumns);
for (var i = 0; i < numberOfRows; i++)
{
RowDefinitions.Add(new RowDefinition {Height = TileHeight});
}
for (var index = 0; index < enumerable.Count; index++)
{
var column = index%MaxColumns;
var row = (int) Math.Floor(index/(float) MaxColumns);
var tile = await BuildTile(enumerable[index]);
Children.Add(tile, column, row);
}
}
private async Task<Layout> BuildTile(object item1)
{
return await Task.Run(() =>
{
var buildTile = (Layout) Activator.CreateInstance(ItemTemplate, item1);
var tapGestureRecognizer = new TapGestureRecognizer
{
Command = Command,
CommandParameter = item1
};
buildTile.GestureRecognizers.Add(tapGestureRecognizer);
return buildTile;
});
}
}
}
<ctrl:GridView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
x:Name="GrdView"
RowSpacing="5"
ColumnSpacing="5"
MaxColumns="2"
TileHeight="120"
CommandParameter="{Binding}"
Command="{Binding StartTaskCommand}"
IsClippedToBounds="False">
</ctrl:GridView>
public ProjectPage()
{
InitializeComponent();
// not sure how to define this in XAML
GrdView.ItemTemplate = typeof(TaskTileTemplate);
}
protected override async void OnAppearing()
{
base.OnAppearing();
await GrdView.BuildTiles(taskPageViewModel.Tasks);
}
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TimeTracker.Pages.Templates.TaskTileTemplate"
BackgroundColor="{Binding Color, Converter={StaticResource HexToColorConverter}}"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand">
<Label FontSize="20" Text="{Binding Name}"
TextColor="{Binding Color, Converter={StaticResource BrightnessInversionConverter}}"
AbsoluteLayout.LayoutBounds=".5,.5,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional" />
<ActivityIndicator IsRunning="{Binding IsBusy}"
IsVisible="{Binding IsBusy}"
AbsoluteLayout.LayoutBounds=".5,.5,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional" />
</AbsoluteLayout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment