【问题标题】:How to open custom dialog box / popup using Xamarin.Forms?如何使用 Xamarin.Forms 打开自定义对话框/弹出窗口?
【发布时间】:2016-03-14 18:36:57
【问题描述】:

我是 Xamarin.Forms 的新手,遇到了一种情况,我想用我的控制详细信息打开一个弹出框 [例如点击父页面查看员工详细信息。

如何使用 Xamarin.Forms 打开自定义对话框/弹出窗口?

任何示例代码将不胜感激?

提前致谢!

【问题讨论】:

    标签: ipad xamarin xamarin.forms


    【解决方案1】:

    如果您仍希望将弹出窗口的代码放在其自己的页面中,您可以按照以下逻辑设置一些自定义渲染器。

    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。主机页面

    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。

    Pete 关于 PushModalAsync / PopModalAsync 的说法对于此解决方案仍然有效(我认为这不是缺点),但您的弹出窗口会以透明背景显示。

    在我看来,这种方法的主要优点是您可以将弹出窗口 XAML/代码定义与主机页面分开,并在您希望显示该弹出窗口的任何其他页面上重复使用它。

    【讨论】:

    • 如果我能给你加分让你做得更好,我会的。感谢您的贡献,尤其是 github 项目非常棒。
    • @Gabor: 有没有可能为安卓实现这个?
    • @Gabor:我在 iPad Simulator (iOS 12.1) 上试用了您的示例。我没有看到弹出窗口 - 它只是一个页面导航到另一个页面......
    【解决方案2】:

    您尝试实现的一般目的可以通过使用 Xamarin.FormsPushModalAsyncPopModalAsync 方法来实现 导航对象。

    这可能足以满足您的需要 - 但是 - 这不是真正的模态。我会在一段小代码sn-p之后解释:-

            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?

    注意 - 虽然您现在可以等待显示第二个页面,然后当该页面被关闭时允许代码在下一行继续执行 - 这仍然不是真正的模态表单。再次计时器或任何执行still的东西都会在父页面上被调用。

    更新 1:-

    要让内容显示在现有内容的顶部,然后只需将其包含在当前页面中,但是在您需要之前使这部分内容不可见。

    如果您使用像 Grid 这样支持同一单元格中的多个子控件的外部容器,那么您将能够实现您想要的。

    您还需要使用填充的 Box 之类的东西,其透明度也将覆盖整个页面,以控制围绕您的内部内容部分的可见、透视部分。

    【讨论】:

    • 但我想让它像一个弹出模式对话框一样出现在父页面上方。根据您的示例,它会打开一个单独的页面,并且上一页不可见。
    • 我已经更新了我的答案(请参阅 Update1),因为它更清楚你想要实现的目标。
    • 谢谢@Pete,你有相同的示例代码链接吗?
    • 我没有任何指向现有代码的链接,但实现起来应该不会太难。如果您在本网站之外也可以联系到我,请查看我的个人资料了解详情。
    【解决方案3】:

    我遵循上述方法,发现无法在 iOS 7 上运行。 我找到了这个库 BTProgressHUD,你可以修改和使用它。 我通过依赖服务使用它的方法。 弹出窗口的实际库。 https://github.com/nicwise/BTProgressHUD

    以下示例在内部使用 BTProgressHUD 库。

    https://github.com/xximjasonxx/ScorePredictForms

    【讨论】:

      猜你喜欢
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多