2016-04-27 60 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