• 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 }
    View Code

    使用如下:

    <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>
    View Code

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

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

  • 相关阅读:
    ArrayList与LinkedList区别
    ArrayList底层原理
    nginx启用https访问
    云服务器搭建 Nginx 静态网站
    在云服务器上(CentOS)上安装Node
    文本超出显示省略号CSS
    vue使用改变element-ui主题色
    vue中的select框的值动态绑定
    vue项目对axios的全局配置
    使用crypto-js对数据进行AES加密、解密
  • 原文地址:https://www.cnblogs.com/devin_zhou/p/8334129.html
Copyright © 2020-2023  润新知