2016-04-27 94 views
3

我有一个Xamarin.Forms应用程序,它使用NavigationPage进行正常的屏幕导航。从其中一个屏幕(Stay Detail)中,我需要显示一系列4个顺序模态页面(如向导),收集数据以完成与Stay Detail相关的过程。流程中的每个页面都有一个“取消”按钮,该按钮应允许用户取消向导并返回到保留详细信息。这里是一般流程:清除Xamarin表单模式堆栈

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

这是很容易从StayDetail做PushModalAsync推出modal1,然后PushModalAsync/PopModalAsync个别模态页面之间去。但是,我无法弄清楚从第二模式或更高版本退出模态堆栈的干净方式。什么是最好的方式来做到这一点?

+0

我今天已经有同样的问题。工作在我想出的答案 – Dbl

回答

0

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

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

然后,当他们击中了取消按钮,你会做一个更PopModalAsync(),并会回来的StayDetail页面上,因为你已经弹出所有的情态动词的下面。

如果他们需要很长的路要走回modal1让后modal2,你可以简单的通过,同时创造了新的一页,像这样modal1需要的任何数据:

Modal1Data modalData = new Modal1Data(); 

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

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

+0

一旦你将第二个模式推入堆栈,调用PopModalAsync将会弹出一个,而不是下面的那个。 – pconrey

+0

@pconrey一旦你从“Modal 1”导航到“Modal 2”,“Modal 1”自动弹出。如果你弹出'Modal 2',你会回到你的'StayDetail' – hvaughan3

0

这个解决方案可能会看起来过于复杂的情况下,但它是我用来沟通模态行动之间的随机解决依赖关系(没有帐户目前,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; } 
} 
+0

我想这就是德国人过度工作的刻板印象来自...... – Dbl