學習目標
- App 全域型變數
- 委派 Event 變數
為什麼我會稱這兩個為中介型參數傳遞呢?
因為這兩個方法都要依靠另一個類別內的變數,才有辦法達到 參數傳遞 這個目的。
第一種方法會先在 App 內設定好要使用的全域變數,
那第二種則是先在另一個頁面內設好要委派的事件 (Event) 變數。
先來看 App 的用法~ 相當簡單的
App 全域變數
在 Xamarin.Forms 應用程式內,第一個會被執行的就是 App()
又由於每一支程式內都可以取得 Application.Current 屬性,就可以透過這屬性得到 App() 內設定好的變數。
白話來說,我們可以在 App 類別內建立共用變數。
來看程式,先建立一個 Information 類別:
public class Information { public Information() { Date = DateTime.Today; } public string Name { set; get; } public string Email { set; get; } public string Language { set; get; } public DateTime Date { set; get; } public override string ToString() { return String.Format("{0} / {1} / {2} / {3:d}", String.IsNullOrWhiteSpace(Name) ? "???" : Name, String.IsNullOrWhiteSpace(Email) ? "???" : Email, String.IsNullOrWhiteSpace(Language) ? "???" : Language, Date); } }
這邊的 Information 比之前的多了 Date 的屬性
再來看一下 App:
再來看一下 App:
public class App : Application { // 建立全域變數 public IListInfoCollection { private set; get; } public Information CurrentInfoItem { set; get; } public App() { // 初始化全域變數. InfoCollection = new ObservableCollection (); MainPage = new NavigationPage(new DataTransfer4HomePage()); } … }
當我們在 App 建立好變數後,就能隨意的在 任一頁面 使用他們!
HomePage 可以選擇新增的動作,或點選一筆 ListView 的項目後導入 InfoPage 並做編輯
HomePage
public partial class DataTransfer4HomePage : ContentPage { //建立 app 物件(重點) App app = (App)Application.Current; public DataTransfer4HomePage() { InitializeComponent(); listView.ItemsSource = app.InfoCollection; } //新增按鈕 async void OnGetInfoButtonClicked(object sender, EventArgs args) { // 建立新的 Information 物件給全域變數. app.CurrentInfoItem = new Information(); await Navigation.PushAsync(new DataTransfer4InfoPage()); } // ListView 點選時. async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args) { if (args.SelectedItem != null) { listView.SelectedItem = null; // 取得點選項目值,並指派給全域變數 app.CurrentInfoItem = (Information)args.SelectedItem; await Navigation.PushAsync(new DataTransfer4InfoPage()); } } }
總之,任何要傳遞的物件都交給 app 全域處理...
InfoPage 理所當然的使用全域變數,並取得 HomePage 指派的新值:
InfoPage
public partial class DataTransfer4InfoPage : ContentPage { // 同樣要先建立 app 物件 App app = (App)Application.Current; public DataTransfer4InfoPage() { InitializeComponent(); // 從全域變數取出值,並帶入畫面 Information info = app.CurrentInfoItem; nameEntry.Text = info.Name ?? ""; emailEntry.Text = info.Email ?? ""; if (!String.IsNullOrWhiteSpace(info.Language)) { languagePicker.SelectedIndex = languagePicker.Items.IndexOf(info.Language); } datePicker.Date = info.Date; } protected override void OnDisappearing() { base.OnDisappearing(); // 將畫面的值取出並指派給全域變數 Information info = app.CurrentInfoItem; info.Name = nameEntry.Text; info.Email = emailEntry.Text; int index = languagePicker.SelectedIndex; info.Language = index == -1 ? null : languagePicker.Items[index]; info.Date = datePicker.Date; // 如果值已經存在 list 則取代他 IListlist = app.InfoCollection; index = list.IndexOf(info); if (index != -1) { list[index] = info; } // 不存在則新增 else { list.Add(info); } } }
可以注意的是,因為 list 的型態是 ObservableCollection,當 InfoPage 去更改 list 時,就會自動去刷新 HomePage 的 ListView。
Event 事件委派
這方法和 App 有那麼一點點像,差在說我們把事件建立成一個變數,等待實際的方法委派給他,
痾... 聽不懂沒關係,來看程式碼:
但這次我們要倒回來看,先看一下 InfoPage,我們會先定義好 事件變數,並稍等讓 HomePage 委派實作:
public partial class DataTransfer3InfoPage : ContentPage { // 定義一個事件,並等待委派 public EventHandler< Information> InformationReady; Information info = new Information(); public DataTransfer3InfoPage() { InitializeComponent(); } public void InitializeInfo(Information info) { this.info = info; // 將值帶入畫面 nameEntry.Text = info.Name ?? ""; emailEntry.Text = info.Email ?? ""; if (!String.IsNullOrWhiteSpace(info.Language)) { languagePicker.SelectedIndex = languagePicker.Items.IndexOf(info.Language); } datePicker.Date = info.Date; } protected override void OnDisappearing() { base.OnDisappearing(); info.Name = nameEntry.Text; info.Email = emailEntry.Text; int index = languagePicker.SelectedIndex; info.Language = index == -1 ? null : languagePicker.Items[index]; info.Date = datePicker.Date; // 若 InformationReady 事件非 null,則執行. InformationReady?.Invoke(this, info); } }
在 OnDisappearing 時,會去執行已經委派的 InformationReady 事件。
HomePage
本頁重點在於,我們會將方法委派給 InfoPage 定義好的 InformationReady 事件
public partial class DataTransfer3HomePage : ContentPage { ObservableCollectionlist = new ObservableCollection (); public DataTransfer3HomePage() { InitializeComponent(); listView.ItemsSource = list; } // Button Clicked handler. async void OnGetInfoButtonClicked(object sender, EventArgs args) { DataTransfer3InfoPage infoPage = new DataTransfer3InfoPage(); await Navigation.PushAsync(infoPage); // 委派方法給下一頁的事件 infoPage.InformationReady += OnInfoPageInformationReady; } // ListView 點選項目時 async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args) { if (args.SelectedItem != null) { // Deselect the item. listView.SelectedItem = null; DataTransfer3InfoPage infoPage = new DataTransfer3InfoPage(); await Navigation.PushAsync(infoPage); // 呼叫下一頁的方法,上一小節有教學 infoPage.InitializeInfo((Information)args.SelectedItem); // 委派方法給下一頁的事件 infoPage.InformationReady += OnInfoPageInformationReady; } } void OnInfoPageInformationReady(object sender, Information info) { // 若物件已經存在,則取代他 int index = list.IndexOf(info); if (index != -1) { list[index] = info; } // 不存在則新增 else { list.Add(info); } } }
其實寫起來有點像是上一小節呼叫上頁方法,
但利用事件並委派的好處就是,
不需要事先知道上下頁的類別是什麼,就能執行另一頁的方法。
當然,也不用特地使用 Navigation Stack 去計算並取得頁面物件。
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。