使用MvvmCross从ViewModel显示AlertDialog

时间:2013-06-11 05:48:11

标签: mvvm xamarin.android alertdialog xamarin mvvmcross

我正在使用MvvmCross创建我的Android应用程序,我遇到了以下问题:

当我试图显示在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", (sender, args) => { /* close alertDialog */});

                adb.Create().Show();
            });
    }
}

当我researching时,我发现它的发生是因为传递了对Context的引用而不是AlertDialog.Builder中的Activity。

this topic我发现了以下决定: 通过使用GetService()接收对当前Activity的引用,但我没有找到mvvmcross插件用于IMvxServiceConsumer,IMvxAndroidCurrentTopActivity接口。

我的问题是否可以从ViewModel显示AlertDialog?我怎样才能获得对Activity的引用,而不是Application.Context? 什么是关闭AlertDialog的正确方法,用户将保留在当前视图?

1 个答案:

答案 0 :(得分:12)

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

  • 因为ViewModels应保持独立于平台
  • 因为ViewModels应该是单元可测试的 - 当代码显示对话框时很难进行单元测试

我还建议您不要在ViewModel构造函数中放置这样的代码 - 这些构造函数通常在导航期间调用,并且在转换期间显示Dialog可能会有问题。


有了这些说法,如果您确实希望在任何代码中掌握当前的顶级活动,那么您可以使用IMvxAndroidCurrentTopActivity

执行此操作
public interface IMvxAndroidCurrentTopActivity
{
    Activity Activity { get; }
}

使用此代码,任何代码都可以使用:

获取当前Activity
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界面
  • 理想情况下,我可能会使此接口异步 - 例如使用async或使用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 MvvmCrossUnable run ProgressDialog - BadTokenException while showind