在這篇文章中,我們將會來探討這樣的頁面使用情境該如何進行設計,請參考下圖,在這個頁面中,將會有三個 Switch 控制項,我們希望能夠做到這三個控制項彼此之間的設定選擇是互斥的,也就是,類似一個 Radio Button 的變形應用;當我們選擇了 選項2 之後,選項1就會變成沒有被選擇狀態,同樣的,當選擇了 選項3,此時,選項1,選項2 就會變成沒有被選擇的狀態。
由於 Switch 這個控制項並沒有相對應可以使用命令 Command(其實,這個控制像是沒有提供任何的 命令),這個時候,我們第一個想到的處理方式,就是使用 Prism 提供的 Behavior 行為機制 , 您可參考 Using the EventToCommandBehavior ,設定當 Switch 的 Toggled 事件被觸發的時候,便可以執行 ViewModel 中指定的 DelegateCommand 的委派方法。
不過,在這篇文章中,我們將要來說明另外一種做法,那就是使用我們安裝好的 PropertyChanged.Fody 這個 NuGet 套件所提供的功能,那就是我們可以針對所綁定的資料,設計一個事件方法,一旦這個綁定的資料有所異動的時候,相對應的事件方法就會被執行。
建立測試專案
- 首先,我們先使用 Prism Template Pack 擴充功能所提供的專案樣板,建立起一個 Xamarin.Forms 專案,在這裡我們僅選擇 Android / iOS / UWP 類型的專案;接著,我們需要把 PropertyChanged.Fody NuGet 套件安裝到 .NET Standard 專案類別庫內,並且安裝 FodyWeavers.xml 檔案。
- 我們來設計這篇文章中使用的範例頁面,在這個頁面中,我們使用了三個 Switch 控制項,這三個 Switch 控制項彼此是互斥的,您可以視為這三個 Switch 控制項的行為,會類似於我們 Windows 程式中的 Radio Button;最後,我們會把您選擇的結果,顯示在最後一個 Label 控制項內。
<?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="XFDataChanged.Views.MainPage"
Title="Switch 控制項的資料異動偵測與設計方法">
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="Welcome to Xamarin Forms and Prism!" />
<StackLayout Orientation="Horizontal">
<Label Text="選項 1"/>
<Switch IsToggled="{Binding Option1}"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="選項 2"/>
<Switch IsToggled="{Binding Option2}"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="選項 3"/>
<Switch IsToggled="{Binding Option3}"/>
</StackLayout>
<Label Text="{Binding YourChoice, StringFormat='你選擇的是 {0}'}"/>
</StackLayout>
</ContentPage>
- 我們開始進行 ViewModel 的 C# 商業邏輯程式碼的設計,在這裡,我們需要設計三個所綁定 Switch 的 C# Property 屬性物件,當它本身的值有異動的話,我們需要有個相對應的事件方法被呼叫與執行。不過,我們對於這樣的事件方法,它的名稱需要使用指定的命名規格,那就是
On
你的綁定屬性Changed
其中前的 On 與最後的 Changed 是固定不變的,我們來看個例子,若您的綁定屬性物件為 Option1 ,當使用者在頁面中進行操作,變動了 Option1 的值,這個時候,您的 ViewModel 內的On
Option1Changed
方法,就會被自動呼叫了。為了要能夠讓 Switch 的運作表現如同 Radio 的效果,我們同時也設計了 SetOption 方法
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace XFDataChanged.ViewModels
{
using System.ComponentModel;
using Prism.Events;
using Prism.Navigation;
using Prism.Services;
public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
{
public event PropertyChangedEventHandler PropertyChanged;
public bool Option1 { get; set; }
public bool Option2 { get; set; }
public bool Option3 { get; set; }
public string YourChoice { get; set; }
private readonly INavigationService _navigationService;
public MainPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatingTo(NavigationParameters parameters)
{
}
public void OnOption1Changed()
{
SetOption(nameof(Option1));
}
public void OnOption2Changed()
{
SetOption(nameof(Option2));
}
public void OnOption3Changed()
{
SetOption(nameof(Option3));
}
public void OnNavigatedTo(NavigationParameters parameters)
{
ResetOptions();
}
public void ResetOptions()
{
SetOption(nameof(Option1));
}
public bool CorrelationAction { get; set; }
public void SetOption(string choiceOption)
{
if (CorrelationAction == true) return;
CorrelationAction = true;
switch (choiceOption)
{
case nameof(Option1):
Option1 = true;
Option2 = false;
Option3 = false;
break;
case nameof(Option2):
Option1 = false;
Option2 = true;
Option3 = false;
break;
case nameof(Option3):
Option1 = false;
Option2 = false;
Option3 = true;
break;
default:
break;
}
YourChoice = choiceOption;
CorrelationAction = false;
}
}
}