天天看點

第二十四章:頁面導航(十二)

事件

在方法調用方法和消息中心通信方法中,資訊頁面需要知道首頁的類型。 如果可以從不同類型的頁面調用相同的資訊頁面,這有時是不合需要的。

這個問題的一個解決方案是info類實作一個事件,這就是DataTransfer3中采用的方法。 Information類和XAML檔案與以前的程式相同,但DataTransfer3InfoPage現在實作名為InformationReady的公共事件:

public partial class DataTransfer3InfoPage : ContentPage
{
    // Define a public event for transferring data.
    public EventHandler<Information> InformationReady;
    // Instantiate an Information object for this page instance.
    Information info = new Information();
    public DataTransfer3InfoPage()
    {
        InitializeComponent();
    }
    public void InitializeInfo(Information info)
    {
        // Replace the instance.
        this.info = info;
        // Initialize the views.
        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();
        // Set properties of Information object.
        info.Name = nameEntry.Text;
        info.Email = emailEntry.Text;
        int index = languagePicker.SelectedIndex;
        info.Language = index == -1 ? null : languagePicker.Items[index];
        info.Date = datePicker.Date;
        // Raise the InformationReady event.
        EventHandler<Information> handler = InformationReady;
        if (handler != null)
            handler(this, info);
    }
}           

在OnDisappearing覆寫期間,該類從元素設定資訊屬性,并使用Information對象引發InformationReady事件。

首頁可以在執行個體化資訊頁面之後或在導航到頁面之後為InformationReady事件設定處理程式。 事件處理程式将Information對象添加到ListView或替換現有項:

public partial class DataTransfer3HomePage : ContentPage
{
    ObservableCollection<Information> list = new ObservableCollection<Information>();
    public DataTransfer3HomePage()
    {
        InitializeComponent();
        // Set collection to ListView.
        listView.ItemsSource = list;
    }
    // Button Clicked handler.
    async void OnGetInfoButtonClicked(object sender, EventArgs args)
    {
        DataTransfer3InfoPage infoPage = new DataTransfer3InfoPage();
        await Navigation.PushAsync(infoPage);
        // Set event handler for obtaining information.
         infoPage.InformationReady += OnInfoPageInformationReady;
    }
    // ListView ItemSelected handler.
    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);
            // Set event handler for obtaining information.
            infoPage.InformationReady += OnInfoPageInformationReady;
        }
    }
    void OnInfoPageInformationReady(object sender, Information info)
    {
        // If the object has already been added, replace it.
        int index = list.IndexOf(info);
        if (index != -1)
        {
            list[index] = info;
        }
        // Otherwise, add it.
        else
        {
            list.Add(info);
        }
    }
}           

這種方法存在一些問題。 第一個問題是沒有友善的地方來分離事件處理程式。 資訊頁面在其OnDisappearing覆寫中引發事件。 如果您不确定僅在導航發生時調用OnDisappearing,則首頁無法在處理程式本身中分離事件處理程式。

首頁也不能在其OnAppearing覆寫中分離事件處理程式,因為當資訊頁面傳回到首頁時,調用OnAppearing和OnDisappearing覆寫的順序取決于平台。

如果首頁無法從資訊頁面中分離處理程式,則每個資訊頁面執行個體将繼續維護對首頁的引用,并且不能進行垃圾回收。

當應用程式需要儲存和恢複頁面狀态時,事件處理程式方法也不好。 當程式再次執行時,資訊頁面無法儲存事件的狀态以恢複它。

繼續閱讀