我有一个我写过的MVVM Xamarin Forms框架,当我弹出一个模态对话框时,我正在尝试建立如何覆盖Soft Navigate Back按钮的BackButtonText(在iOS中用于此问题)。
我的导航服务创建了一个自定义模态页面控制器视图模型,该模型又通过IoC容器转换为NavigationPage,如下所示:
public async Task PushModalAsync<T>() where T : INavigationPageModel
{
var navigationmodel = _viewModelFactory.CreateModel<ModalPageControllerViewModel<T>>();
var page = _viewFactory.CreatePage(navigationmodel);
await Navigation.PushModalAsync(page);
}
结果页面以类结构结束:
public class NavigationControllerView : NavigationPage, IView
然后让我设置我自己的ViewModel的BindingContext。在此之后,我希望有约束力为我做其余的繁重工作。在此导航控制器视图上设置绑定上下文将我的第一页(在本例中是唯一的页面,即模态对话框)推送到导航堆栈。
var page = _viewFactory.CreatePage(_viewModel.CurrentPage);
PushAsync(page);
然后页面在我的设备上正确显示为弹出页面,显示我的导航栏,并显示工具栏项目,正如我所期望的那样。所有绑定似乎都像我想象的那样工作,我可以从我的ViewModel中删除该页面。到目前为止一切都很好。
现在(我在这里猜测)因为模态对话框是模态堆栈上唯一的页面,可能是因为它是模态,因此“模态”页面不显示“后退”按钮。我想要做的是在模态弹出窗口中显示“后退”按钮并覆盖其文本,以便显示“取消”。这应该与iOS中的“创建新邮件”弹出页面构思相同,因此我可以将其解雇。
我已阅读了不少文章,表明它应该像放置代码一样“简单”
NavigationPage.SetBackButtonText(page, "Some title")
甚至可能包括
行NavigationPage.SetHasBackButton(page, this)
但忽略了告诉我这确实发生在哪里。有人建议这应该发生在页面的构造函数中,但是哪个页面?它是NavigationPage本身的页面(根据我的理解,它是托管模态页面的包装器。)
注意:我在NavigationPage中托管了Modal页面,以便继续显示导航栏和工具栏项。
我已经尝试将NavigationPage.SetBackButtonText和NavigationPage.SetHasBackButton放在所有地方,但它们似乎都没有做任何事情。
阅读另一篇文章表明,这些方法仅影响“下一页”,所以我尝试在显示之前将相同的方法应用到上一页,但仍然没有成功。但实际上我们没有以前的页面作为模式弹出窗口,也是堆栈中唯一的东西。
我在这里可能会出错的任何想法?
答案 0 :(得分:1)
所以看起来这里的问题是你试图在模态导航页面中显示一个后退按钮,但是导航页面的堆栈中没有任何内容可以返回。
您可以尝试在模式导航页面的堆栈中放置一个“虚拟”页面,然后再显示其他任何页面,然后您会看到一个后退按钮,可能会更改文本以显示“取消”。这种方法需要一些额外的布线来处理后退导航,并且当你“取消”回到虚拟页面时,可能会弹出模态堆栈的模态导航。
免责声明:我没有尝试过这种方法,也不知道会出现什么其他问题。
答案 1 :(得分:0)
我已经为这个问题努力了几天。正确的选择可能是为iOS和Android编写自定义渲染器。 Xamarin forums中有一个很好的iOS示例。我的用例是我刚刚在现有应用程序中添加了标签栏。一旦启动,我需要将现有过程设置为模态,以便隐藏选项卡栏。当前进程使用“后退”按钮在进程中向后导航,我希望继续将其用于该目的。但是,仅推动模式页面并不会提供“后退”按钮。我正在使用Michael Ridlands FreshMVVM,并使用PushPageModelWithNewNavigation()
在导航堆栈中注入一个虚拟页面:
await CoreMethods.PushPageModelWithNewNavigation<DummyPageModel>(store, false);
这将在我的标签导航页面上呈现一个模式页面。我的DummyPage.xaml
只是默认模板。 DummyPageModel跟踪其是否被推送或弹出,并推送实际页面还是弹出回到选项卡导航页面:
public class DummyPageModel : FreshBasePageModel
{
private object _data;
private bool _isPushed = true;
public override void Init(object initData) => _data = initData;
protected override async void ViewIsAppearing(object sender, EventArgs e)
{
base.ViewIsAppearing(sender, e);
if (_isPushed)
{
_isPushed = false;
await CoreMethods.PushPageModel<StorePageModel>(_data);
}
else
{
await CoreMethods.PopPageModel();
}
}
}
使用这种方法的用户体验是相对无缝的,因此在这一点上希望足够好。