Xamarin.Forms自定义GridView

Xamarin.Forms自定义GridView

在开发中,我们经常用到以格子的形式来展示我们的数据,在很多平台的控件中我们叫做GridView,

在Xamarin.Forms中没有原生的GridView,这里简单介绍一种利用Xamarin.Forms中的Grid来实现

GridView的方法。

原理就是对Grid动态添加RowDefinition和ColumnDefinition。

代码如下:

  1 using System;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.Diagnostics;
  5 using System.Linq;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 using System.Windows.Input;
  9 using Xamarin.Forms;
 10 using Xamarin.Forms.Xaml;
 11
 12 namespace XFPractice.CustomView
 13 {
 14     [XamlCompilation(XamlCompilationOptions.Compile)]
 15     public partial class GridView : Grid
 16     {
 17
 18         public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(GridView));
 19         public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command),typeof(ICommand), typeof(GridView));
 20         public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate),typeof(DataTemplate),typeof(GridView),null);
 21
 22         public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(GridView), default(IEnumerable<object>), propertyChanged: OnItemsSourcePropertyChanged);
 23
 24
 25         private int _maxColumns = 2;
 26         private float _tileHeight = 100;
 27
 28         public GridView()
 29         {
 30             InitializeComponent();
 31             for (var i = 0; i < MaxColumns; i++)
 32             {
 33                 ColumnDefinitions.Add(new ColumnDefinition());
 34             }
 35         }
 36
 37
 38
 39         public static void OnItemsSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
 40         {
 41             ((GridView)bindable).UpdateTiles();
 42         }
 43
 44
 45
 46         public DataTemplate ItemTemplate
 47         {
 48             get { return (DataTemplate)GetValue(ItemTemplateProperty); }
 49             set { SetValue(ItemTemplateProperty, value); }
 50         }
 51
 52         public IEnumerable ItemsSource
 53         {
 54             get { return (IEnumerable)GetValue(ItemsSourceProperty); }
 55             set {SetValue(ItemsSourceProperty, value);}
 56         }
 57
 58         public int MaxColumns
 59         {
 60             get { return _maxColumns; }
 61             set { _maxColumns = value; }
 62         }
 63
 64         public float TileHeight
 65         {
 66             get { return _tileHeight; }
 67             set { _tileHeight = value; }
 68         }
 69
 70         public object CommandParameter
 71         {
 72             get { return GetValue(CommandParameterProperty); }
 73             set { SetValue(CommandParameterProperty, value); }
 74         }
 75
 76         public ICommand Command
 77         {
 78             get { return (ICommand)GetValue(CommandProperty); }
 79             set { SetValue(CommandProperty, value); }
 80         }
 81
 82         public async Task BuildTiles(IEnumerable tiles)
 83         {
 84             // Wipe out the previous row definitions if they‘re there.
 85             if (RowDefinitions.Any())
 86             {
 87                 RowDefinitions.Clear();
 88             }
 89             Children.Clear();
 90             if (tiles == null)
 91             {
 92                 return;
 93             }
 94             var enumerable = tiles as IList ?? tiles.Cast<object>().ToArray();
 95             var numberOfRows = Math.Ceiling(enumerable.Count / (float)MaxColumns);
 96             HeightRequest = TileHeight * numberOfRows;
 97             InvalidateLayout();
 98             for (var i = 0; i < numberOfRows; i++)
 99             {
100                 RowDefinitions.Add(new RowDefinition { Height = TileHeight });
101             }
102             int ItemCount = enumerable.Count;
103             int size = (int)numberOfRows * MaxColumns;
104
105             for (var index = 0; index < size; index++)
106             {
107                 var column = index % MaxColumns;
108                 var row = (int)Math.Floor(index / (float)MaxColumns);
109                 if (index  < ItemCount)
110                 {
111                     var tile = await BuildTile(enumerable[index]);
112                     Children.Add(tile, column, row);
113                 }
114                 else
115                 {
116                     var tile = await BuildEmptyTile();
117                     Children.Add(tile, column,row);
118                 }
119             }
120         }
121
122         public async void UpdateTiles()
123         {
124             await BuildTiles(ItemsSource);
125         }
126
127         private async Task<Xamarin.Forms.View> BuildEmptyTile()
128         {
129             return await Task.Run(() =>
130             {
131                 var content = ItemTemplate?.CreateContent();
132                 if (!(content is Xamarin.Forms.View) && !(content is ViewCell)) throw new Exception(content.GetType().ToString());
133                 var buildTile = (content is Xamarin.Forms.View) ? content as Xamarin.Forms.View : ((ViewCell)content).View;
134                 return buildTile;
135             });
136
137         }
138
139         private async Task<Xamarin.Forms.View> BuildTile(object item)
140         {
141             return await Task.Run(() =>
142             {
143                 var content = ItemTemplate?.CreateContent();
144                 if (!(content is Xamarin.Forms.View) && !(content is ViewCell)) throw new Exception(content.GetType().ToString());
145                 var buildTile = (content is Xamarin.Forms.View) ? content as Xamarin.Forms.View : ((ViewCell)content).View;
146                 buildTile.BindingContext = item;
147                 var tapGestureRecognizer = new TapGestureRecognizer
148                 {
149                     Command = Command,
150                     CommandParameter = item
151                 };
152                 buildTile.GestureRecognizers.Add(tapGestureRecognizer);
153                 return buildTile;
154             });
155
156         }
157
158     }
159 }

使用如下:

<controls:GridView
                        x:Name="mGridView"
                        HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        TileHeight="48"
                        MaxColumns ="5"
                        ItemsSource="{Binding UserInfoList,Mode=TwoWay}">
                        <controls:GridView.ItemTemplate>
                            <DataTemplate>
                                <Grid Padding="8" HeightRequest="48" WidthRequest="48" HorizontalOptions="Center">
                                    <Image Source="{Binding HeadImage}" HeightRequest="32" WidthRequest="32" Aspect="AspectFill"/>
                                </Grid>
                            </DataTemplate>
                        </controls:GridView.ItemTemplate>
                    </controls:GridView>

这段代码有一个问题,ItemsSource绑定ListSource后,当ListSource发生增加减少不会触发GridView的刷新,

之后将ListSource重新new一个对象后,才会触发propertyChanged从而刷新GridView。

原文地址:https://www.cnblogs.com/devin_zhou/p/8334129.html

时间: 2024-09-09 07:50:16

Xamarin.Forms自定义GridView的相关文章

Xamarin.Forms自定义用户界面控件实现一个HybridWebView(混合webview)

原文:Implementing a HybridWebView呈现一个特定于平台的视图 Xamarin.Forms自定义用户界面控件应该来自视图类(View class),用于在屏幕上放置布局和控件.本文演示了如何为HybridWebView(混合webview)自定义控件创建自定义渲染器,该控件演示了如何增强特定平台的web控件,以允许从JavaScript调用c#代码. 每一个Xamarin.Forms视图为每个创建本地控件实例的平台提供了相应的渲染器.当一个视图被Xamarin.Forms

Xamarin.Forms 自定义 TapGestureRecognizer 附加属性

While creating Xamarin.Forms applications, definitely you are going to need TapGestureRecognizer often. Implementing it in XAML many times may end up with a lot of unnecessary code. Let’s take a look at that simple clickable Image: 1 <Image Source=&quo

Xamarin.forms 自定义dropdownview控件

一 基本说明 想用xamarin做个像美团这样的下拉列表进行条件选择的功能,但是但是找了半天好像没有现成的,也没有其他类似的控件可以走走捷径,再则也没有找到popwindow之类的东东,这里只好使用stacklaout+contentview做一个伪下拉,因为没有fragement那样的控件,所以没有华丽丽的叠加层,也没有华丽丽的遮罩,由于xamarin的动画只发现了缩放,旋转,淡入淡出,位置变换(研究不深入,大神勿喷),暂时没有发现下拉一类的动画,所以暂时用缩放来展现下来的内容,使下拉的时候不

Xamarin.Forms 调用 腾讯地图SDK

Xamarin.Forms研究了好一段时间了,最近一直在学习中,想尝试一下调用其他的SDK,就如腾讯地图SDK(申请容易). 完成此次项目得感谢以下链接: http://www.cnblogs.com/jtang/p/4698496.html 其他文档参考: 腾讯地图SDK(安卓)文档 这里面有详细的使用过程(当然里面的代码是不适用C#的,不过要从这里下载SDK,也有如何申请Key的过程,请参考阅读) Xamarin.Forms自定义每个平台的控件文档 里面有如何根据不同的平台条件下,调用其他页

自定义xamarin.forms Entry 背景色

创建 一个Xamarin.Forms自定义控件. ? 自定义Entry控件可以通过继承来创建Entry控制,显示在下面的代码示例: public class MyEntry : Entry { } ? 消费 从Xamarin.Forms自定义控件. 该MyEntry控制可在XAML通过宣布其位置的命名空间,使用控制元素的命名空间前缀引用在PCL项目. 下面的代码示例显示了如何MyEntry控制可以通过一个XAML页面消耗: <ContentPage ... xmlns:local="clr

菜鸟的Xamarin.Forms前行之路——按钮的按下抬起事件的监控(可扩展至其他事件)

提问:监控按钮的点击事件,可以通过按钮的Click事件,或者Command绑定,那么如何监控按钮的按下与抬起,或者移动,长按,双击等事件? 解决方法:各个平台自定义渲染依赖注入. 共享项目PCL: 1先定义一个继承Button的实体类NewButton.cs public class NewButton : Button { public event EventHandler Pressed; public event EventHandler Released; public virtual

Xamarin.Forms特殊的视图BoxView

BoxView是Xamarin.Forms比较特殊的视图.该视图构建非常简单,其作用也很单一.它的作用就是构成一个特定颜色的色块.在界面设计中,它可以充当纯色图片来使用,从而大大减少软件包的体积.同时,它也可以作为图片和自定义空间预加载的占位.该视图默认大小为40*40,如果不设置对齐方式,会填充整个父容器.用户可以使用HeightRequest和WidthRequest指定需要的大小.

Xamarin Forms ch2 - Xlabs

Xamarin.iOS and Xamarin.Droid proved that C# code can be used to develop mobile apps, and majority of business logic written in c# can be shared on both mobile platforms development. However, the development of User Interface is still heavily dependi

【转】Xamarin Forms 介绍

特此声明,本篇博文转自:http://blog.csdn.net/kinfey/article/details/29621381 什么是 Xamarin Forms ? Xamarin Forms 是一个高效创建跨平台用户界面的库 .通过Xamarin Forms 可以一次编码生成基于主流移动平台(iOS, Android, Windows Phone)的应用界面.和HTML 5 不同, 它是一套原生的界面解决方案,这意味着通过Xamarin Forms 渲染的界面是与底层API 紧密相连, 那