天天看点

第二十四章:页面导航(十二)

事件

在方法调用方法和消息中心通信方法中,信息页面需要知道主页的类型。 如果可以从不同类型的页面调用相同的信息页面,这有时是不合需要的。

这个问题的一个解决方案是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覆盖的顺序取决于平台。

如果主页无法从信息页面中分离处理程序,则每个信息页面实例将继续维护对主页的引用,并且不能进行垃圾回收。

当应用程序需要保存和恢复页面状态时,事件处理程序方法也不好。 当程序再次执行时,信息页面无法保存事件的状态以恢复它。

继续阅读