傳統上 Xamarin.Forms 並沒有提供類似 GridView 這樣的控制項,也就是可以使用多 Column 的方式來顯示集合資料,但是其他的行為與 ListView 一樣。
在這份筆記中,將會測試與使用 DLToolkit.Forms.Controls.FlowListView
這個 NuGet 套件,就可以達成使用 GridView 控制項的效果。
要使用這個功能,您需要在方案中加入這個 DLToolkit.Forms.Controls.FlowListView
NuGet 套件到所有的專案內;下面螢幕截圖為實際執行結果。
範例專案
需要安裝 NuGet 套件
要完成這個筆記中的效果,你需要在方案中安裝底下的 NuGet 套件
Xamarin.FFImageLoading.Forms
DLToolkit.Forms.Controls.FlowListView
範例說明
首先,需要定義這個集合的資料模型。
在這個,建立了一個 SampleItems1 資料模型,裡面有 Title / Color / ImageUrl 這三個屬性。
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;
namespace XFHListView.Models
{
public class SampleItems1 : BindableBase
{
#region Title
private string _Title;
public string Title
{
get { return this._Title; }
set { this.SetProperty(ref this._Title, value); }
}
#endregion
#region Color
private Color _Color;
public Color Color
{
get { return this._Color; }
set { this.SetProperty(ref this._Color, value); }
}
#endregion
#region ImageUrl
private string _ImageUrl;
public string ImageUrl
{
get { return this._ImageUrl; }
set { this.SetProperty(ref this._ImageUrl, value); }
}
#endregion
public SampleItems1()
{
}
}
}
接著需要在 ViewModel 內定義所有資料綁定的集合資料,並且要進行集合資料的初始化,可以參考底下程式碼。
在這個 ViewModel 內,集合資料將會使用 ObservableCollection<SampleItems1>
型別,並且儲存在 MyDatas 這個物件內。
在建構式內,呼叫了 Init() 方法,針對 MyDatas 進行產生實際物件並且進行資料初始化。
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using XFHListView.Models;
namespace XFHListView.ViewModels
{
public class SimpleSamplePageViewModel : BindableBase
{
#region MyDatas
private ObservableCollection<SampleItems1> _MyDatas;
public ObservableCollection<SampleItems1> MyDatas
{
get { return _MyDatas; }
set { SetProperty(ref _MyDatas, value); }
}
#endregion
#region 使用者點選項目
private SampleItems1 _使用者點選項目;
public SampleItems1 使用者點選項目
{
get { return this._使用者點選項目; }
set { this.SetProperty(ref this._使用者點選項目, value); }
}
#endregion
public DelegateCommand 使用者點選Command { get; set; }
public readonly IPageDialogService _dialogService;
public SimpleSamplePageViewModel(IPageDialogService dialogService)
{
_dialogService = dialogService;
Init();
使用者點選Command = new DelegateCommand(() =>
{
_dialogService.DisplayAlertAsync("訊息", $"你選取的是 {使用者點選項目.Title}", "OK");
});
}
public void Init()
{
MyDatas = new ObservableCollection<SampleItems1>();
var howMany = new Random().Next(100, 500);
for (int i = 0; i < howMany; i++)
{
MyDatas.Add(new SampleItems1() { Title = string.Format("項目 {0}", i) });
}
}
}
}
有的 Model / ViewModel,接下來,就是要定義 View,可以參考底下 XAML 。
這個頁面 XAML 內容相當的簡單,根項目為 ContentPage,並且其兒子為 FlowListView
;不過,由於這個 FlowListView
控制項並不是 Xamarin.Forms 預設命名空間所提供的,因此,需要在跟項目內另外定義一個命名空間 xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
,這樣,就可以使用前置詞 flv
來引用 FlowListView
這個控制項。
FlowListView
這個控制項內,使用了 FlowColumnCount="3"
宣告了這個 GridView 效果共有三個 Column,並且每筆紀錄並沒有使用分隔線,這是使用了這個宣告:SeparatorVisibility="None"
另外,使用了 HasUnevenRows="False"
設定每筆紀錄都是等高;當使用者點選了清單內的某個項目,可以使用 FlowItemTappedCommand
來綁定 ViewModel 內的某個 DelegateCommand ,就可以在 ViewModel 內撰寫相關點擊後的處理邏輯;而使用者點選後的項目,也會透過 FlowLastTappedItem
這個屬性,將其綁定到 ViewModel 內的某個屬性,也就是說,當使用者點選某個項目,就可以透過該 ViewModel 內的屬性,取得使用者當時點選的項目內容;最後,該 FlowListView 要顯示的資料清單內容,將會透過 FlowItemsSource
屬性來進行資料綁定。
最後,與 ListView 相同,每筆資料,可以透過 FlowListView.FlowColumnTemplate
來設定這些資料項目要使用何種格式來顯示。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="XFHListView.Views.SimpleSamplePage"
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
Title="簡單範例">
<flv:FlowListView
FlowColumnCount="3"
SeparatorVisibility="None"
HasUnevenRows="False"
FlowItemTappedCommand="{Binding 使用者點選Command}"
FlowLastTappedItem="{Binding 使用者點選項目}"
FlowItemsSource="{Binding MyDatas}" HeightRequest="100"
>
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Label HorizontalOptions="Fill" VerticalOptions="Fill"
XAlign="Center" YAlign="Center" Text="{Binding Title}"/>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
</ContentPage>