博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第二十四章:页面导航(四)
阅读量:7167 次
发布时间:2019-06-29

本文共 6834 字,大约阅读时间需要 22 分钟。

执行模式

通常,除了应用程序需要从用户获取关键信息的特殊情况外,您的应用程序可能会使用无模式页面。 然后,应用程序可以显示用户在输入此关键信息之前无法解除的模态页面。
但是,一个小问题是Android或Windows Phone用户可以通过按设备上的标准后退按钮返回上一页。 要强制执行模式 - 确保用户在离开页面之前输入所需信息 - 应用程序必须禁用该按钮。
ModalEnforcement程序演示了这种技术。 主页仅包含一个Button:

代码隐藏文件通过导航到模式页面来处理按钮的Clicked事件:

public partial class ModalEnforcementHomePage : ContentPage{    public ModalEnforcementHomePage()    {        InitializeComponent();    }    async void OnGoToButtonClicked(object sender, EventArgs args)    {        await Navigation.PushModalAsync(new ModalEnforcementModalPage());    }}

ModalEnforcementModalPage的XAML文件包含两个Entry元素,一个Picker元素和一个标记为Done的Button。 标记比您预期的更广泛,因为它包含一个MultiTrigger,只有当某些内容被输入到两个Entry元素中并且某些内容也被输入到Picker中时,才会将按钮的IsEnabled属性设置为True。 这个MultiTrigger需要三个隐藏的Switch元素,使用第23章“触发器和行为”中讨论的技术:

C#
F#
Objective C
Swift
Java

在现实生活中,可能还会检查电子邮件地址是否有效。 XAML文件中的简单逻辑只检查是否存在至少一个字符。

这是首次出现的模态页面,当时尚未输入任何内容。 请注意,“完成”按钮已禁用:
2019_04_16_095311
通常,用户仍然可以按Android和Windows Phone屏幕左下方的标准后退按钮返回主页面。 要禁止“后退”按钮的正常行为,模态页面必须覆盖虚拟OnBackButtonPressed方法。 您可以在此覆盖中提供自己的后退按钮处理并返回true。 要完全禁用“后退”按钮,只需返回true而不执行任何其他操作。 要允许进行默认的“后退”按钮处理,请调用基类实现。 以下是ModalEnforcementModalPage的代码隐藏文件的用法:

public partial class ModalEnforcementModalPage : ContentPage{    public ModalEnforcementModalPage()    {        InitializeComponent();    }    protected override bool OnBackButtonPressed()    {        if (doneButton.IsEnabled)        {            return base.OnBackButtonPressed();        }        return true;    }    async void OnDoneButtonClicked(object sender, EventArgs args)    {        await Navigation.PopModalAsync();    }}

仅当启用XAML文件中的“完成”按钮时,OnBackButtonPressed覆盖才会调用方法的基类实现并返回从该实现返回的值。 这会导致模态页面返回到调用它的页面。 如果禁用“完成”按钮,则覆盖返回true,表示它已完成执行所需的“后退”按钮所需的所有操作。

像往常一样,完成按钮的Clicked处理程序只调用PopModalAsync。
Page类还定义了一个SendBackButtonPressed,它导致调用OnBackButtonPressed方法。 应该可以通过调用此方法为“完成”按钮实现Clicked处理程序:

void OnDoneButtonClicked(object sender, EventArgs args){    SendBackButtonPressed();}

虽然这适用于iOS和Android,但它目前无法在Windows运行时平台上运行。

在实际编程中,您更有可能使用ViewModel来累积用户输入模态页面的信息。 在这种情况下,ViewModel本身可以包含一个属性,该属性指示输入的所有信息是否有效。
MvvmEnforcement程序使用这种技术,并包含一个名为LittleViewModel的ViewModel:

namespace MvvmEnforcement{    public class LittleViewModel : INotifyPropertyChanged    {        string name, email;        string[] languages = { "C#", "F#", "Objective C", "Swift", "Java" };        int languageIndex = -1;        bool isValid;        public event PropertyChangedEventHandler PropertyChanged;        public string Name        {            set            {                if (name != value)                {                    name = value;                    OnPropertyChanged("Name");                    TestIfValid();                }            }            get { return name; }        }        public string Email        {            set            {                if (email != value)                {                    email = value;                    OnPropertyChanged("Email");                    TestIfValid();                }            }            get { return email; }        }        public IEnumerable
Languages { get { return languages; } } public int LanguageIndex { set { if (languageIndex != value) { languageIndex = value; OnPropertyChanged("LanguageIndex"); if (languageIndex >= 0 && languageIndex < languages.Length) { Language = languages[languageIndex]; OnPropertyChanged("Language"); } TestIfValid(); } } get { return languageIndex; } } public string Language { private set; get; } public bool IsValid { private set { if (isValid != value) { isValid = value; OnPropertyChanged("IsValid"); } } get { return isValid; } } void TestIfValid() { IsValid = !String.IsNullOrWhiteSpace(Name) && !String.IsNullOrWhiteSpace(Email) && !String.IsNullOrWhiteSpace(Language); } void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }}

Name和Email属性的类型为string,用于绑定Entry元素的Text属性。 LanguageIndex属性旨在绑定到Picker的SelectedIndex属性。 但是LanguageIndex的set访问器使用该值从Languages集合中的字符串数组中设置string类型的Language属性。

只要Name,Email或LanguageIndex属性发生更改,就会调用TestIfValid方法来设置IsValid属性。 此属性可以绑定到Button的IsEnabled属性。
MvvmEnforcement中的主页与ModalEnforcement中的主页相同,但当然模态页面的XAML文件更简单并实现了所有数据绑定:

标记包含对ViewModel中的属性的四个绑定。

模态页面的代码隐藏文件负责实例化LittleViewModel并将对象设置为页面的BindingContext属性,它在构造函数中执行。 构造函数还访问ViewModel的Languages集合以设置Picker的Items属性。 (遗憾的是,Items属性不受可绑定属性的支持,因此不可绑定。)
该文件的其余部分与ModalEnforcement中的模态页面非常相似,只是OnBackButtonPressed覆盖访问LittleViewModel的IsValid属性以确定是调用基类实现还是返回true:

public partial class MvvmEnforcementModalPage : ContentPage{    public MvvmEnforcementModalPage()    {        InitializeComponent();        LittleViewModel viewModel = new LittleViewModel();        BindingContext = viewModel;        // Populate Picker Items list.        foreach (string language in viewModel.Languages)        {            picker.Items.Add(language);        }    }    protected override bool OnBackButtonPressed()    {        LittleViewModel viewModel = (LittleViewModel)BindingContext;        return viewModel.IsValid ? base.OnBackButtonPressed() : true;    }    async void OnDoneButtonClicked(object sender, EventArgs args)    {        await Navigation.PopModalAsync();    }}

转载地址:http://fqtwm.baihongyu.com/

你可能感兴趣的文章