使用MvvmCross从ViewModel显示AlertDialog

使用MvvmCross从ViewModel显示AlertDialog,mvvm,xamarin.android,android-alertdialog,xamarin,mvvmcross,Mvvm,Xamarin.android,Android Alertdialog,Xamarin,Mvvmcross,我正在使用MvvmCross创建我的Android应用程序,我面临以下问题: 当我试图显示AlertDialog时,它是在ViewModel中创建的 “出现未处理的异常:Android.Views.WindowManagerBadtokenexException” 当我还是个孩子的时候,我发现这是因为引用传输到了上下文,而不是AlertDialog.Builder中的活动 在这方面,我作出了以下决定: 通过使用GetService()接收对当前活动的引用,但我没有找到用于IMvxServiceC

我正在使用MvvmCross创建我的Android应用程序,我面临以下问题:

当我试图显示AlertDialog时,它是在ViewModel中创建的

出现未处理的异常:Android.Views.WindowManagerBadtokenexException

当我还是个孩子的时候,我发现这是因为引用传输到了上下文,而不是AlertDialog.Builder中的活动

在这方面,我作出了以下决定: 通过使用GetService()接收对当前活动的引用,但我没有找到用于IMvxServiceConsumer、IMVXSandroidCurrentTopActivity接口的mvvmcross插件

我的问题是,我可以从ViewModel显示AlertDialog吗?我如何获得对活动的引用,而不是对Application.Context的引用?
关闭AlertDialog的正确方法是什么,用户将保留在当前视图上?

通常,您不应该将此类代码放入ViewModels中

  • 因为ViewModels应该保持平台独立性
  • 因为ViewModels应该是可单元测试的,而且当代码显示对话框时很难进行单元测试
我还建议您不要将这样的代码放在ViewModel构造函数中-这些构造函数通常在导航期间调用,在转换期间显示对话框可能会有问题


说到这些,如果您确实想在任何代码中掌握当前的top活动,那么您可以使用
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();
var-top=Mvx.Resolve();
var act=顶级活动;
if(act==null)
{
//这可能发生在转换期间
//-您需要确保您的代码不会发生这种情况
抛出新的MvxException(“无法获取当前顶级活动”);
}
var dlg=新建AlertDialog.Builder(act);
//...
dlg.Create().Show();

中讨论了
IMvxAndroidCurrentTopActivity
的使用

该问题/答案中采用的方法也是我通常从ViewModel显示对话框的方法之一:

  • 我将创建一个
    IFooDialog
    界面
  • 理想情况下,我可能会使此接口异步-例如,使用
    async
    或使用
    Action
    回调参数
  • 在每个平台上,我都会在UI项目中实现它
  • 当需要对话框时,
    ViewModel
    s可以使用
    IFooDialog
    ,并且每个平台都可以使用适当的UI操作进行响应
这种“对话服务”类型的方法在Mvvm中很常见-例如,请参阅以下文章(尽管这篇文章非常特定于Windows!)


这里还有一些关于MvvmCross和dialogs的其他问题-尽管它们可能包含对旧版本v1或vNext代码的引用-例如和

好的,我正在尝试这些东西:)我同意从VM使用UI不是“风水”;)但WinPhone和iPhone平台已经推出,我只需要安卓版本的应用程序。将来,在我的新项目中,我将必须根据佳能MVVM进行开发:)Stuart,一个关于
IMvxAndroidCurrentTopActivity
的简短问题:即使当前顶级活动发生变化,它是否始终是同一个实例?背景:我不喜欢服务位置,相反,我的类采用显式依赖关系。如果我的一个单例类对
IMvxAndroidCurrentTopActivity
具有构造函数依赖性,并且它仍然可以在当前活动上运行,那么它会工作吗?@DanielHilgarth请将新问题作为新问题提问。我想这样会更容易写,更容易读,更容易回复。谢谢。@Stuart:哈,我不知道我发表了多少次这样的评论。现在我犯了同样的错误…;-)问题是:谢谢。
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();