当我试图显示在viewmodel中创建的AlertDialog时,
出现“未处理的异常:Android.Views.WindowManagerBadTokenException”.
public class Myviewmodel : Mvxviewmodel { public ICommand ShowAlertCommand { get; private set; } public Authorizationviewmodel() { ShowAlertCommand = new MvxCommand(() => { var adb = new AlertDialog.Builder(Application.Context); adb.SetTitle("Title here"); adb.SetMessage("Message here"); adb.SetIcon(Resource.Drawable.Icon); adb.SetPositiveButton("OK",(sender,args) => { /* some logic */}); adb.SetNegativeButton("Cancel",args) => { /* close alertDialog */}); adb.Create().Show(); }); } }
当我是researching时,我发现它的发生是因为传递了对Context的引用而不是AlertDialog.Builder中的Activity.
在this topic年,我发现了以下决定:
通过使用GetService()接收对当前Activity的引用,但我没有找到mvvmcross插件用于IMvxServiceConsumer,IMvxAndroidCurrentTopActivity接口.
我的问题是我可以从viewmodel显示AlertDialog吗?我怎样才能获得对Activity的引用,而不是Application.Context?
什么是关闭AlertDialog的正确方法,用户将留在当前视图?
解决方法
>因为viewmodels应该保持与平台无关
>因为viewmodels应该是可单元测试的 – 当代码显示对话框时很难进行单元测试
我还建议你不要在viewmodel构造函数中放置这样的代码 – 这些构造函数通常在导航期间调用,并且在转换期间显示Dialog可能会有问题.
有了这些说法,如果你想在任何代码中掌握当前的顶级Activity,那么你可以使用IMvxAndroidCurrentTopActivity来做到这一点.
public interface IMvxAndroidCurrentTopActivity { Activity Activity { get; } }
var top = Mvx.Resolve<IMvxAndroidCurrentTopActivity>(); var act = top.Activity; if (act == null) { // this can happen during transitions // - you need to be sure that this won't happen for your code throw new MvxException("Cannot get current top activity"); } var dlg = new AlertDialog.Builder(act); //... dlg.Create().Show();
在MvvmCross: How to pass Android context down to MvxCommand?中讨论了IMvxAndroidCurrentTopActivity的使用
在该问题/答案中采用的方法也是我通常从viewmodel显示对话框的方法之一:
>我会创建一个IFooDialog接口
>理想情况下,我可能会使这个接口异步 – 例如使用异步或使用Action< DialogResult>回调参数
>在每个平台上,我都会在UI项目中实现它
>然后,当需要对话框时,viewmodel可以使用IFooDialog,并且每个平台都可以使用适当的UI操作进行响应
这种“对话服务”类型的方法在Mvvm中很常见 – 例如看到像http://www.codeproject.com/Articles/36745/Showing-Dialogs-When-Using-the-MVVM-Pattern这样的文章(虽然那篇文章非常适合Windows!)
此处还有一些关于MvvmCross和对话框的其他问题 – 尽管它们可能包含对较早的v1或vNext代码的引用 – 例如Alerts or Popups in MvvmCross和Unable run ProgressDialog – BadTokenException while showind