使用 CollectionView 建立一個能以 GridView 呈現的效果
CollectionView 現階段還是在 Preview 階段,當 Xamarin.Forms 4.0 (現階段 Xamarin.Forms 的版本是 3.6) 正式推出的時候,將可以使用這個 CollectionView 檢視。這個檢視除了具有 ListView 的功能之外,它還可以使用 GridView 的模式來顯示出每筆資料,現在,就來實際建立這個專案來體驗設計過程吧。
該文件的專案原始碼可以透過 GitHub 來取得
建立一個 使使用 FlexLayout 專案
- 開啟 Visual Studio 2019 程式
- 當 Visual Studio 2019 開始 視窗 出現之後,請點選左下角的 [建立新專案] 選項
- 當 [建立新專案] 對話窗出現之後,請在中間最上方的搜尋文字輸入盒中輸入 [prism] 關鍵字,搜尋所有與 Prism 有關的專案樣板
- 請選擇 [Prism Blank App (Xamarin.Forms)] 這個專案樣板
- 當出現 [設定新的專案] 對話窗,請在 [專案名稱] 輸入 [XF3002]
- 最後點選該對話窗右下方的 [建立] 按鈕
- 現在將會看到 [PRISM PROJECT WIZARD] 對話窗,請勾選 ANDROID, iOS 這兩個行動裝置平台,接著在底下 [Container] 下拉選單,選擇 Unity 項目
- 最後,點選 [CREATE PROJECT] 按鈕,以便產生 Xamarin.Forms 專案
安裝需要用到的 PropertyChanged.Fody NuGet 套件
- 當這個 Xamarin.Forms 專案建立成功之後,請在該方案中,找到 Xamarin.Forms 使用的專案(這是一個 .NET Standard 類別庫,簡稱為 SCL ),請在該專案中,使用滑鼠右擊 [相依性] 節點,選擇 [管理 NuGet 套件] 選項
- 在 [NuGet: XXX] 視窗中,點選 [瀏覽] 標籤頁次,並且在下方的搜尋文字輸入盒中,輸入 [propertychanged.fody] 關鍵字,搜尋出這個 NuGet 套件
- 當出現 [PropertyChanged.Fody] NuGet 套件,請點選該套件,並且點選右方的 [安裝] 按鈕,將這個套件安裝到 Xamarin.Forms 專案內
- 請查看 Xamarin.Forms 專案內,並沒有 [FodyWeavers.xml] 這個檔案,因此,使用滑鼠右擊 Xamarin.Forms 專案節點,選擇 [建置] 選項
- 當建置完成之後,在這個 Xamarin.Forms 專案內將會出現 [FodyWeavers.xml] 檔案
安裝需要用到的 Xamarin.Essentials NuGet 套件
- 在 [NuGet: XXX] 視窗中,搜尋文字輸入盒中,輸入 [Xamarin.Essentials] 關鍵字,搜尋出這個 NuGet 套件
- 當出現 [Xamarin.Essentials] NuGet 套件,請點選該套件,並且點選右方的 [安裝] 按鈕,將這個套件安裝到 Xamarin.Forms 專案內
修正因為安裝 Xamarin.Essentials 帶來的錯誤
現在,可以從 Visual Studio 2019 的錯誤視窗中,看到底下的錯誤訊息
錯誤 NU1107 偵測到 Xamarin.Android.Support.Compat 有版本衝突。請將 Xamarin.Android.Support.Compat 28.0.0.1 直接安裝/參考到專案 XF3002.Android 來解決此問題。
XF3002.Android -> XF3002 -> Xamarin.Essentials 1.1.0 -> Xamarin.Android.Support.Compat (>= 28.0.0.1)
XF3002.Android -> Xamarin.Android.Support.Design 27.0.2.1 -> Xamarin.Android.Support.Compat (= 27.0.2.1). XF3002.Android D:\Vulcan\GitHub\XCourse19\XF3002\XF3002\XF3002.Android\XF3002.Android.csproj 1
想要解決此一問題:
- 使用滑鼠右擊方案節點(方案總管最上方的那個節點),選擇 [管理方案的 NuGet 套件]
- 點選 [更新] 標籤頁次
- 勾選該標籤頁次內的所有項目
- 點選右上方的更新按鈕,就可以升級這些套件到最新版本了
升級 Xamarin.Forms 套件到 4.0 版本
- 同樣的,使用滑鼠右擊方案節點(方案總管最上方的那個節點),選擇 [管理方案的 NuGet 套件]
- 點選 [已安裝] 標籤頁次
- 點選 [Xamarin.Forms] 套件項目
- 勾選 [包括搶鮮版] 檢查盒,要求顯示搶鮮版的套件清單
- 在右方的 Xamarin.Forms 套件清單中,勾選所有的專案
- 在下方的版本下拉選單中,選擇 4.0 以上的版本,現階段只能夠看到 4.0.0.346134-pre9 這個版本
- 點選右下方 [安裝] 按鈕,將這個 4.0 的 Xamarin.Forms 套件安裝到所有專案內
建立資料模型
- 滑鼠右擊 Xamarin.Forms 專案,選擇 [加入] > [新增資料夾]
- 將新增資料夾的名稱設定為 [Models]
- 滑鼠右擊剛剛建立的 [Models] 資料夾,選擇 [加入] > [類別]
- 在 [新增項目] 對話窗下方的 [名稱] 欄位中,輸入 [MyData]
- 點選右下方的 [新增] 按鈕
- 將底下程式碼填入到這個新建立的類別檔案內
public class MyData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
public int OrderId { get; set; }
}
修正該 Android 專案的 MainActivity.cs
因為現階段 CollectionView 還是在預覽階段,所以,需要在原生專案的進入點內,要執行
Xamarin.Forms.Forms.Init
這個方法前,要增加先執行底下的方法。- 打開 [MainActivity.cs] 檔案
- 將第 18 行,此行沒有任何程式碼,在此加入這個 C# 敘述
Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
建立使用 CollectionView 的頁面與商業邏輯
- 在 [Views] 資料夾內,打開 [MainPage.xaml] 檔案
- 修正使用底下的 XAML 語言宣告
在這裡的 CollectionView 將會透過 [ItemsSource] 這個可綁定屬性,從 ViewModel 物件內取得要顯示的清單集合資料,並且使用 [SelectionMode] 屬性,設定使用者僅能夠使用單選的方式來選取,最後透過 [SelectionChangedCommand] 這個命令,綁定到 ViewModel 內的 ICommand 屬性,也就是當使用者點選任一項目之後,將會觸發這個命令。
在 CollectionView 內,可以使用 [CollectionView.ItemsLayout] 來設定此次要顯示的資料格式,在這裡將會使用 [GridItemsLayout] 這個屬性來指定使用 GridView 的模式來呈現,並且是以垂直方式來顯示資料。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XF3002.Views.MainPage"
Title="CollectionView 的應用練習">
<StackLayout
>
<CollectionView
x:Name="cv"
ItemsSource="{Binding myItemList}"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
SelectionChangedCommand="{Binding SelectionChangedCommand}"
>
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="LightGray" CornerRadius="3" HasShadow="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Label
HorizontalOptions="Start"
Text="{Binding Name}"
FontAttributes="Bold"
FontSize="20"/>
<Label
HorizontalOptions="End" VerticalOptions="End"
Text="{Binding OrderId}"
TextColor="Red"
FontSize="16"/>
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
- 在 [ViewModels] 資料夾內,打開 [MainPageViewModel.xaml] 檔案
- 修正使用底下的 C# 程式碼
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XF3002.ViewModels
{
using System.Collections.ObjectModel;
using System.ComponentModel;
using Prism.Events;
using Prism.Navigation;
using Prism.Services;
using XF3002.Models;
public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<MyData> myItemList { get; set; } = new ObservableCollection<MyData>();
public MyData SelectedItem { get; set; }
public int GridItemsLayoutSpan { get; set; } = 2;
public DelegateCommand SelectionChangedCommand { get; set; }
private readonly INavigationService navigationService;
private readonly IPageDialogService dialogService;
public MainPageViewModel()
{
ReadData();
}
public MainPageViewModel(INavigationService navigationService, IPageDialogService dialogService)
{
this.navigationService = navigationService;
this.dialogService = dialogService;
SelectionChangedCommand = new DelegateCommand(() =>
{
dialogService.DisplayAlertAsync("Info", SelectedItem.Name, "OK");
});
}
public void OnNavigatedFrom(INavigationParameters parameters)
{
}
public void OnNavigatedTo(INavigationParameters parameters)
{
ReadData();
}
public void OnNavigatingTo(INavigationParameters parameters)
{
}
public void ReadData()
{
int cc = 1;
for (int i = 0; i < 10; i++)
{
myItemList.Add(new MyData() { Name = "Baboon", OrderId=cc++ });
myItemList.Add(new MyData() { Name = "Capuchin Monkey", OrderId = cc++ });
myItemList.Add(new MyData() { Name = "Blue Monkey", OrderId = cc++ });
myItemList.Add(new MyData() { Name = "Squirrel Monkey", OrderId = cc++ });
myItemList.Add(new MyData() { Name = "Golden Lion Tamarin", OrderId = cc++ });
myItemList.Add(new MyData() { Name = "Howler Monkey", OrderId = cc++ });
myItemList.Add(new MyData() { Name = "Japanese Macaque", OrderId = cc++ });
}
}
}
}