繁体   English   中英

清除 Xamarin 表单模式堆栈

[英]Clear Xamarin Forms Modal Stack

我有一个 Xamarin.Forms 应用程序,它使用 NavigationPage 进行普通屏幕导航。 在其中一个屏幕(Stay Detail)中,我需要显示一系列 4 个连续模式页面(如向导),这些页面收集数据以完成与 Stay Detail 相关的流程。 流程中的每个页面都有一个“取消”按钮,该按钮应允许用户取消向导并返回到“保持详细信息”。 这是一般流程:

            modal1 -> modal2 -> modal3 -> modal4
           /                                    \
 StayDetail                                      StayDetail

从 StayDetail 执行 PushModalAsync 以启动 modal1,然后在各个模式页面之间执行 PushModalAsync/PopModalAsync 非常容易。 但是,我想不出一种干净的方法从第二个模态或更高版本退出模态堆栈。 这样做的最佳方法是什么?

每次用户导航到下一个模态时,您不能只执行以下操作吗?

await Navigation.PushModalAsync(new modal2()); //Send user to new modal2 pages
await Navigation.PopModalAsync(); //Pop modal1 page

然后当他们点击取消按钮时,你会再做一次PopModalAsync()并返回到StayDetail页面,因为你已经弹出了下面的所有模态。

如果他们在获得modal2之后需要一种方法回到modal1,你可以简单地传递modal1需要的任何数据,同时创建一个新的页面:

Modal1Data modalData = new Modal1Data();

await Navigation.PushModalAsync(new modal1(modalData)); //Push old modal with previously entered data
await Navigation.PopModalAsync(); //Pop modal2 page

您甚至可以在导航回modal1之前保存已从modal2输入的数据,这样当用户返回到modal2时,他们的所有信息仍会显示在屏幕上。

对于你的情况,这个解决方案可能看起来过于复杂,但是我正在使用模式操作之间进行通信以解决依赖关系(没有帐户存在,id缺失,同时删除数据等)而不会丢失类型安全性。

考虑向导/模态系列的一种方法是,下一页取决于前一页,而且大多数情况下你会想要使用你的子模态的结果。

我希望这有帮助:

public static class ModalManager
{
    public static bool TryRespondModal<TData>(this IModalResponse<TData> source, TData data, bool autoPop = true, bool animate = false)
    {
        if (Application.Current.MainPage.Navigation.ModalStack.Count <= 0)
            return false;

        source.ModalRequestComplete.SetResult(data);

        if (autoPop)
            Application.Current.MainPage.Navigation.PopModalAsync(animate);

        return true;
    }

    public static Task<TData> GetResponseAsync<TData>(this IModalResponse<TData> source)
    {
        source.ModalRequestComplete = new TaskCompletionSource<TData>();
        return source.ModalRequestComplete.Task;
    }
}

public enum WizardState
{
    Indeterminate = 0,
    Complete = 1,
    Canceled = 2
}

public class WizardModel
{
    public WizardState State { get; set; }

    public List<string> Page1Values { get; set; } = new List<string>();
    public List<string> Page2Values { get; set; } = new List<string>();
    public List<string> Page3Values { get; set; } = new List<string>();
}

public abstract class WizardPage : IModalResponse<WizardModel>
{
    public WizardModel Model { get; set; }

    public ICommand NextCommand { get; set; }

    public ICommand PreviousCommand { get; set; }

    public ICommand CancelCommand { get; set; }

    protected WizardPage(WizardModel model)
    {
        Model = model;
        NextCommand = new Command(NextButtonPressed);
        PreviousCommand = new Command(PreviousButtonPressed);
        CancelCommand = new Command(PreviousButtonPressed);
    }

    protected abstract IModalResponse<WizardModel> GetNextPage();

    protected virtual void CancelButtonPressed()
    {
        Model.State = WizardState.Canceled;
        this.TryRespondModal(Model);
    }

    protected virtual void PreviousButtonPressed()
    {
        // you're dropping down on the level of dependent windows here so you can tell your previous modal window the result of the current response
        this.TryRespondModal(Model);
    }

    protected virtual async void NextButtonPressed()
    {
        var np = GetNextPage();
        if (Model.State == WizardState.Complete || np == null || (await np?.GetResponseAsync()).State == WizardState.Complete)
            PersistWizardPage();

        // all following modal windows must have run through - so you persist whatever your page has done, unless you do that on the last page anyway. and then tell the previous
        // modal window that you're done
        this.TryRespondModal(Model);
    }

    protected virtual void PersistWizardPage()
    {
        // virtual because i'm lazy
        throw new NotImplementedException();
    }

    public TaskCompletionSource<WizardModel> ModalRequestComplete { get; set; }
}

public class Page1 : WizardPage
{

    public Page1(WizardModel model) : base(model)
    {
    }

    protected override IModalResponse<WizardModel> GetNextPage()
    {
        return new Page2(Model);
    }
}

public class Page2 : WizardPage
{
    public Page2(WizardModel model) : base(model)
    {
    }

    protected override IModalResponse<WizardModel> GetNextPage()
    {
        return new Page3(Model);
    }
}

public class Page3 : WizardPage
{
    public Page3(WizardModel model) : base(model)
    {
    }

    protected override IModalResponse<WizardModel> GetNextPage()
    {
        return null;
    }

    protected override void NextButtonPressed()
    {
        this.Model.State = WizardState.Complete;
        base.NextButtonPressed();
    }
}

public interface IModalResponse<TResponseType>
{
    TaskCompletionSource<TResponseType> ModalRequestComplete { get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM