XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2018/04/17

Xamarin.Forms ListView 集合資料多選

這篇文章將會探討如何在 Xamarin.Forms 中,設計原生 ListView 具有多選功能,如同下圖所示。在 Xamarin.Forms 中的 ListView 控制項,本身是沒有預設提供多選功能,僅提供單選並且可以觸發一個點選的事件,不過,若要讓 ListView 具有多選紀錄的功能,我們就需要另外設計一個 UI,當使用者選擇多筆紀錄之後,接著觸發這個 UI,就可以根據剛剛選擇完成的紀錄,進行相關的商業邏輯處理。
Xamarin.Forms ListView Multiple Select
因此,在底下的程式碼中,使用者可以點選 ListView 的不同紀錄,一旦點選之後,該紀錄就會被選取到了,並且該紀錄的背景顏色會呈現綠色,代表該紀錄已經被選取了;當然,您也可以再度點選剛剛的紀錄,這筆紀錄就會取消選取,記錄背景顏色就會恢復成為灰色。最後,若多選紀錄操作完成之後,我們可以點選導航工具列的按鈕 結束 這個按鈕,這個時候在 ViewModel 內相對應的 DelegateCommand 委派方法,就會開始計算這次使用者總共點選了幾筆紀錄,並且顯示在螢幕的上方。

本篇文章的專案原始碼位於 XFMulSelLV

建立 ListView 的頁面 View 檢視

  • 首先,請打開 MainPage.xaml 檔案,使用底下 XAML 宣告標記替換掉
  • 在這個 ListView 控制項中,其實就是一般我們在設計 ListView 所用到的 XAML 語法相同,不過,我們在 ViewCell 中,您會看到有兩個 BoxView 控制項,第一個 BoxView 控制項的顏色是灰色,而第二個 BoxView 控制項的顏色是綠色,同時,我們也看到第二個 BoxView 的 XAML 標記宣告為 <BoxView Color="LightGreen" IsVisible="{Binding IsSelected}"/> ,這表示了,這個 BoxView 是否會顯示出來,將會取決於當時這筆紀錄在 ViewModel 中的 IsSelected 屬性值是否為 True。
MainPage
<?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:Behaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
             xmlns:prism = "clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel= "True"
             x:Class="XFMulSelLV.Views.MainPage"
             Title="集合資料多選">

    <ContentPage.ToolbarItems>
        <ToolbarItem Text="結果"
                     Command="{Binding ShowResultCommand}"/>
    </ContentPage.ToolbarItems>

    <Grid>
        <Label Text="{Binding Title}"/>
        <ListView
            Margin="0,20,0,0"
            ItemsSource="{Binding PeopleCollection}"
            SelectedItem="{Binding PersonSelected}"
            HasUnevenRows="True"
            SeparatorVisibility="None"
            >
            <ListView.Behaviors>
                <Behaviors:EventToCommandBehavior
                    EventName="ItemTapped"
                    Command="{Binding PersonTappedCommand}"/>
            </ListView.Behaviors>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            <BoxView Color="LightGray"/>
                            <BoxView Color="LightGreen"
                                     IsVisible="{Binding IsSelected}"/>
                            <StackLayout
                                Orientation="Vertical"
                                HorizontalOptions="Fill" VerticalOptions="Start"
                                >
                                <Label
                                    Text="{Binding Name}"
                                    FontSize="30"
                                    />
                                <Label
                                    Text="{Binding Age}"
                                    FontSize="20"
                                    />
                            </StackLayout>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>

</ContentPage>

建立 ListView 的頁面 ViewModel 檢視模型

  • 首先,請打開 MainPageViewModel.cs 檔案,使用底下 C# 程式碼替換掉
  • 我們在這個檔案中,宣告了一個 ListView 的紀錄節點類別,Person,在這個類別中,有著姓名、年紀與是否選取這三個屬性。另外,為了要能夠讓您的選取動作,可以正常更新 IsSelected 屬性,進而使用當時的 IsSelected 值,更新頁面 UI 顯示,這個時候,請記得務必要將 Person 類別,要能夠實作 INotifyPropertyChanged 介面。
  • 我們設計頁面 ViewModel 的導航事件 OnNavigatedTo,在這裡進行 ListView 要顯示的記錄之初始化動作,我們在這裡產生出 100 筆的紀錄。
  • 我們有在頁面中,使用 ListView.Behaviors 來宣告一個 ListView 的事件,觸發發生後,要執行 ViewModel 中 PersonTappedCommand 命令,而我們在這個 PersonTappedCommand 命令委派方法中,執行這個敘述 PersonSelected.IsSelected = !PersonSelected.IsSelected; ,因此,若這筆紀錄尚未被選取,則 PersonSelected.IsSelected 就是 false,此時,我們將 PersonSelected.IsSelected 的值變更成為 true,因為 PersonSelected.IsSelected 值有變動了,就會觸發 INPC (Notification Property Changed) 的綁定事件,此時,頁面上就會更新 PersonSelected.IsSelected 為 true 的狀態下,將 ViewCell 內的第二個 BoxView 顯示出來。
C# CSharp
public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsSelected { get; set; }

}

public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
{
    public event PropertyChangedEventHandler PropertyChanged;
    public ObservableCollection<Person> PeopleCollection { get; set; } = new ObservableCollection<Person>();
    public Person PersonSelected { get; set; }
    public string Title { get; set; } 
    public DelegateCommand PersonTappedCommand { get; set; }
    public DelegateCommand ShowResultCommand { get; set; }
    private readonly INavigationService _navigationService;

    public MainPageViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
        PersonTappedCommand = new DelegateCommand(() =>
        {
            PersonSelected.IsSelected = !PersonSelected.IsSelected;
        });
        ShowResultCommand = new DelegateCommand(() =>
        {
            var fooCount = 0;
            foreach (var item in PeopleCollection)
            {
                if(item.IsSelected == true)
                {
                    fooCount++;
                }
            }
            Title = $"共選擇 {fooCount} 筆紀錄";
        });
    }

    public void OnNavigatedFrom(NavigationParameters parameters)
    {

    }

    public void OnNavigatingTo(NavigationParameters parameters)
    {

    }

    public void OnNavigatedTo(NavigationParameters parameters)
    {
        PeopleCollection.Clear();
        for (int i = 0; i < 100; i++)
        {
            PeopleCollection.Add(new Person
            {
                Name = $"Name{i}",
                Age = i,
                IsSelected = false
            });
        }
    }

}




沒有留言:

張貼留言