事件
在方法调用方法和消息中心通信方法中,信息页面需要知道主页的类型。 如果可以从不同类型的页面调用相同的信息页面,这有时是不合需要的。
这个问题的一个解决方案是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覆盖的顺序取决于平台。
如果主页无法从信息页面中分离处理程序,则每个信息页面实例将继续维护对主页的引用,并且不能进行垃圾回收。
当应用程序需要保存和恢复页面状态时,事件处理程序方法也不好。 当程序再次执行时,信息页面无法保存事件的状态以恢复它。