2014-09-22 4 views
8

Я новичок в Xamarin.Forms и придерживался ситуации, когда я хочу открыть всплывающее окно с моими контрольными данными (например, Просмотреть сведения о сотрудниках] при щелчке на родительской странице.Как открыть собственное диалоговое окно/всплывающее окно с использованием Xamarin.Forms?

Как открыть собственное диалоговое окно/всплывающее окно с использованием Xamarin.Forms?

Любой пример кода будет оценен по достоинству?

Заранее благодарен!

ответ

3

Общая цель того, что вы пытаетесь достичь может быть достигнуто с помощью PushModalAsync и PopModalAsync методы Xamarin.FormsНавигация объект.

Скорее всего, это достаточно хорошо для того, что вам нужно - Однако - это не совсем модально. Я объясню после небольшого фрагмента кода: -

 StackLayout objStackLayout = new StackLayout() 
     { 
     }; 
     // 
     Button cmdButton_LaunchModalPage = new Button(); 
     cmdButton_LaunchModalPage.Text = "Launch Modal Window"; 
     objStackLayout.Children.Add(cmdButton_LaunchModalPage); 
     // 
     cmdButton_LaunchModalPage.Clicked += (async (o2, e2) => 
     { 
      ContentPage objModalPage = new ContentPage(); 
      objModalPage.Content = await CreatePageContent_Page2(); 
      // 
      await Navigation.PushModalAsync(objModalPage); 
      // 
      // Code will get executed immediately here before the page is dismissed above. 
     }); 
     // 
     return objStackLayout; 



    private async Task<StackLayout> CreatePageContent_Page2() 
    { 
     StackLayout objStackLayout = new StackLayout() 
     { 
     }; 
     // 
     Button cmdButton_CloseModalPage = new Button(); 
     cmdButton_CloseModalPage.Text = "Close"; 
     objStackLayout.Children.Add(cmdButton_CloseModalPage); 
     // 
     cmdButton_CloseModalPage.Clicked += ((o2, e2) => 
     { 
      this.Navigation.PopModalAsync(); 
     }); 
     // 
     return objStackLayout; 
    } 

Проблема с вышесказанным, что

  await Navigation.PushModalAsync(objModalPage); 

немедленно вернуться после анимации.

Хотя вы не можете взаимодействовать с предыдущей страницы, как мы показываем новый NavigationPage с кнопкой Закрыть показали - родителюнавигация Страница по-прежнему выполняется за кулисами параллельно.

Итак, если бы у вас были какие-то таймеры или что-то еще, они все равно вызывались бы, если бы вы не остановили их.

Вы также можете использовать подход TaskCompletionSource, как описано в следующем сообщении также How can I await modal form dismissal using Xamarin.Forms?.

Примечание - что, хотя вы можете теперь ждут 2-й страницы отображения, а затем, когда эта страница уволенный позволяет выполнение кода, чтобы продолжить на следующей строке - это до сих пор не истинно модальный форма. Опять же, на родительской странице будут вызываться таймеры или что-либо, выполняющее еще.

Update 1: -

Чтобы иметь содержание появляется поверх существующего содержимого, то просто включите его на текущей странице, однако сделать этот раздел контента невидимым до тех пор, пока это необходимо.

Если вы используете внешний контейнер, такой как сетка Grid, которая поддерживает несколько дочерних элементов управления в одной и той же ячейке, вы сможете достичь того, чего хотите.

Вы также хотите использовать что-то вроде заполненного Коробку с прозрачностью, которая также будет охватывать всю страницу, чтобы контролировать видимую, сквозную секцию, которая окружает ваш внутренний раздел контента.

+0

Но я хочу, чтобы он, как модальное диалоговое окно всплывающего окна, которое появится над родительской страницей. В соответствии с вашим примером он открывает отдельную страницу, а предыдущая страница недоступна для просмотра. –

+0

Теперь я обновляю свой ответ (см. Update1), и теперь он более четко показывает, чего вы пытаетесь достичь. – Pete

+0

Спасибо @Pete, есть ли у вас какая-нибудь ссылка для кода примера? –

13

Если вы все еще хотите, чтобы код вашего всплывающего окна на собственной странице, вы можете настроить некоторые собственные средства визуализации в следующей логике.

1. ModalPage &, соответствующий рендерер

public class ModalPage : ContentPage { } 

public class ModalPageRenderer : PageRenderer { 
    protected override void OnElementChanged(VisualElementChangedEventArgs e) 
    { 
     base.OnElementChanged(e); 
     this.View.BackgroundColor = UIColor.Clear; 
     this.ModalPresentationStyle = UIModalPresentationStyle.OverCurrentContext; 
    } 

    public override void ViewDidLayoutSubviews() 
    { 
     base.ViewDidLayoutSubviews(); 
     SetElementSize (new Size (View.Bounds.Width, View.Bounds.Height)); 
    } 
} 

2. HostPage

public class ModalHostPage : ContentPage, IModalHost 
{ 
    #region IModalHost implementation 

    public Task DisplayPageModal(Page page) 
    { 
     var displayEvent = DisplayPageModalRequested; 

     Task completion = null; 
     if (displayEvent != null) 
     { 
      var eventArgs = new DisplayPageModalRequestedEventArgs(page); 
      displayEvent(this, eventArgs); 
      completion = eventArgs.DisplayingPageTask; 
     } 

     // If there is no task, just create a new completed one 
     return completion ?? Task.FromResult<object>(null); 
    } 

    #endregion 

    public event EventHandler<DisplayPageModalRequestedEventArgs> DisplayPageModalRequested; 

    public sealed class DisplayPageModalRequestedEventArgs : EventArgs 
    { 
     public Task DisplayingPageTask { get; set;} 

     public Page PageToDisplay { get; } 

     public DisplayPageModalRequestedEventArgs(Page modalPage) 
     { 
      PageToDisplay = modalPage; 
     } 
    } 
} 

3. HostPage рендерер

public class ModalHostPageRenderer: PageRenderer 
{ 
    protected override void OnElementChanged(VisualElementChangedEventArgs e) 
    { 
     base.OnElementChanged(e); 

     if(e.OldElement as ModalHostPage != null) 
     { 
      var hostPage = (ModalHostPage)e.OldElement; 
      hostPage.DisplayPageModalRequested -= OnDisplayPageModalRequested; 
     } 

     if (e.NewElement as ModalHostPage != null) 
     { 
      var hostPage = (ModalHostPage)e.NewElement; 
      hostPage.DisplayPageModalRequested += OnDisplayPageModalRequested; 
     } 
    } 

    void OnDisplayPageModalRequested(object sender, ModalHostPage.DisplayPageModalRequestedEventArgs e) 
    { 
     e.PageToDisplay.Parent = this.Element; 
     var renderer = RendererFactory.GetRenderer (e.PageToDisplay); 
     e.DisplayingPageTask = this.PresentViewControllerAsync(renderer.ViewController, true); 
    } 
} 

Тогда это просто, как позвонить await ModalHost.DisplayPageModal(new PopUpPage()); со страницы вашего хоста или в этом конкретном случае из ViewModel позади.

Что говорит Пит о PushModalAsync/PopModalAsync, остается в силе и для этого решения (что, на мой взгляд, не является недостатком), но ваше всплывающее окно появится с прозрачным фоном.

Основным преимуществом этого подхода, на мой взгляд, является то, что вы можете отображать всплывающее определение XAML/кода отдельно от главной страницы и повторно использовать его на любой другой странице, где вы хотите показать это всплывающее окно.

+1

Простая демонстрационная программа здесь: https://github.com/gaborv/xam-forms-transparent-modal – Gabor

+0

Как уже указывалось, это решение работает только в iOS8 + – Gabor

+0

Если бы я мог дать вам бонусные баллы за то, что вы шли выше и выше, я бы. Спасибо за ваш вклад, проект github в частности был потрясающим. –

0

Я следовал за этим подходом и нашел невозможным работать на iOS 7. Я нашел эту библиотеку BTProgressHUD, которую вы можете изменять и использовать. Я использую его методы службой Dependency. Фактическая библиотека для всплывающих окон. https://github.com/nicwise/BTProgressHUD

В следующем примере библиотека BTProgressHUD используется внутри страны.

https://github.com/xximjasonxx/ScorePredictForms