App类中介
在Xamarin.Forms应用程序中,在公共代码项目中执行的第一个代码是通常名为App的类的构造函数,该类派生自Application。 在程序终止之前,此App对象保持不变,并且程序中的任何代码都可以通过静态Application.Current属性使用它。 该属性的返回值是Application类型,但将其强制转换为App很简单。
这意味着App类是存储必须在整个应用程序中访问的数据的好地方,包括从一个页面传输到另一个页面的数据。
DataTransfer4版本程序中的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);
}
}
此版本的构造函数将Date属性设置为今天的日期。 在该程序的先前版本中,信息实例的属性是从信息页面上的各种元素设置的。 在这种情况下,Date属性是从DatePicker设置的,默认情况下将其Date属性设置为当前日期。 在DataTransfer4中,如您所见,信息页面上的元素是从Information对象中的属性初始化的,因此在Information类中设置Date属性只会使程序的功能保持一致。
这是DataTransfer4中的App类。 请注意名为InfoCollection和CurrentInfoItem的公共属性。 在创建DataTransfer4HomePage之前,构造函数将InfoCollection初始化为ObservableCollection 对象:
public class App : Application
{
public App()
{
// Create the ObservableCollection for the Information items.
InfoCollection = new ObservableCollection<Information>();
MainPage = new NavigationPage(new DataTransfer4HomePage());
}
public IList<Information> InfoCollection { private set; get; }
public Information CurrentInfoItem { set; get; }
__
}
App中InfoCollection属性的可用性允许DataTransfer4HomePage将其直接设置为ListView的ItemsSource属性:
public partial class DataTransfer4HomePage : ContentPage
{
App app = (App)Application.Current;
public DataTransfer4HomePage()
{
InitializeComponent();
// Set collection to ListView.
listView.ItemsSource = app.InfoCollection;
}
// Button Clicked handler.
async void OnGetInfoButtonClicked(object sender, EventArgs args)
{
// Create new Information item.
app.CurrentInfoItem = new Information();
// Navigate to info page.
await Navigation.PushAsync(new DataTransfer4InfoPage());
}
// ListView ItemSelected handler.
async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args)
{
if (args.SelectedItem != null)
{
// Deselect the item.
listView.SelectedItem = null;
// Get existing Information item.
app.CurrentInfoItem = (Information)args.SelectedItem;
// Navigate to info page.
await Navigation.PushAsync(new DataTransfer4InfoPage());
}
}
}
请注意两种不同但相似的方式,即实现Button的Clicked处理程序和ListView的ItemSelected处理程序。 在导航到DataTransfer4InfoPage之前,两个处理程序都将App类的CurrentInfoItem属性设置为Information实例。 但Clicked处理程序将CurrentInfoItem属性设置为新实例,而ItemSelected处理程序将其设置为ListView中的选定项。
其他所有内容都由DataTransfer4InfoPage处理。 info页面可以从存储在App类的CurrentInfoItem属性中的Information对象初始化页面上的元素:
public partial class DataTransfer4InfoPage : ContentPage
{
App app = (App)Application.Current;
public DataTransfer4InfoPage()
{
InitializeComponent();
// Initialize the views.
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();
// Set properties of Information object.
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;
// If the object has already been added to the collection, replace it.
IList<Information> list = app.InfoCollection;
index = list.IndexOf(info);
if (index != -1)
{
list[index] = info;
}
// Otherwise, add it.
else
{
list.Add(info);
}
}
}
信息页面仍然需要覆盖其OnDisappearing方法以设置Information对象的属性,并可能将其添加到ListView集合或替换相同的对象以触发重绘。 但是info页面不需要直接访问ListView,因为它可以从App类的InfoCollection属性获取ObservableCollection。
此外,如果您需要保存和恢复页面状态,App类中的所有内容都可用。
让我们看看它是如何工作的。