我是Xamarin.Forms的新手并且遇到了我想打开一个带有我的控制细节的弹出框的情况[例如单击父页面查看“员工详细信息”。
如何使用Xamarin.Forms打开自定义对话框/弹出窗口?
任何示例代码都会受到赞赏吗?
提前致谢!
答案 0 :(得分:15)
如果您仍希望将弹出式代码放在自己的页面中,可以按照以下逻辑设置一些自定义渲染器。
<强> 1。 ModalPage&amp;相应的渲染器
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。
Pete所说的关于PushModalAsync / PopModalAsync的内容对于这个解决方案仍然有效(我认为这不是一个缺点),但你的弹出窗口会以透明的背景出现。
在我看来,这种方法的主要优点是,您可以将弹出式XAML /代码定义与主机页面分开,并在您希望显示该弹出窗口的任何其他页面上重复使用它。
答案 1 :(得分:3)
您尝试实现的目标的一般目的可以通过使用 Xamarin.Forms PushModalAsync 和 PopModalAsync 方法来实现>导航对象。
这可能足以满足您的需求 - 然而 - 这不是真正的模态。我将在一个小代码片段后解释: -
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?中所述。
注意 - 尽管您现在可以等待显示第二页,然后当该页面被解除时允许代码执行在下一行继续 - 这仍然不是一个模态形式即可。再次定时器或任何执行仍然的内容将在父页面上被调用。
更新1: -
要让内容显示在现有内容的顶部,只需将其包含在当前页面上,但是在您需要之前,请将此部分内容隐藏起来。
如果你在同一个单元格中使用支持多个子控件的 Grid 之类的外部容器,那么你将能够达到你想要的效果。
您还需要使用填充 Box 之类的内容,其透明度也会覆盖整个页面,以控制内部内容部分周围的可见,透视部分。
答案 2 :(得分:0)
我遵循上述方法,发现无法在iOS 7上运行。 我发现这个库BTProgressHUD你可以修改和使用。 我通过依赖服务使用它的方法。 弹出窗口的实际库。 https://github.com/nicwise/BTProgressHUD
以下示例在内部使用BTProgressHUD库。