You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVVMCross中使用Acr.UserDialogs:自定义通知弹窗及实例注册问题

解决Xamarin Android MVVMCross中Acr.UserDialogs注册与自定义弹窗问题

我来帮你一步步解决这两个问题,先搞定服务注册的报错,再实现带自定义布局的通知弹窗。


一、修复IUserDialogs注册的"instance"错误

你遇到的注册错误,核心原因是Acr.UserDialogs的实例是平台相关的,不能在跨平台的App.cs里注册,必须在Android项目的Setup类中完成平台服务的注册,具体步骤如下:

  1. 初始化Acr.UserDialogs到Android上下文
    在Android项目的MainActivity.cs的OnCreate方法中添加初始化代码:
using Acr.UserDialogs;

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    // 把当前Activity传入,初始化UserDialogs
    UserDialogs.Init(this);
}
  1. 在Setup类中注册IUserDialogs服务
    找到Android项目中的Setup.cs(继承自MvxAndroidSetup<Core.App>),重写InitializePlatformServices方法:
protected override void InitializePlatformServices()
{
    base.InitializePlatformServices();
    // 注册UserDialogs的单例实例
    Mvx.IoCProvider.RegisterSingleton<IUserDialogs>(UserDialogs.Instance);
}

这样就能解决"object does not contain a definition for instance"的错误了——之前你可能在跨平台的App.cs里尝试访问UserDialogs.Instance,但这个属性是Android平台特有的,必须在Android项目的Setup中注册。


二、实现带自定义布局的通知弹窗

Acr.UserDialogs的默认Alert并不支持自定义布局,所以我们需要基于MVVMCross的MvxDialogFragment来实现自己的弹窗,结合你已有的notification.axml布局,步骤如下:

1. 创建自定义DialogFragment(Android项目)

新建一个CustomNotificationDialog.cs类,继承自MvxDialogFragment,用来加载你的自定义布局并传递数据:

using Android.App;
using Android.OS;
using Android.Views;
using MvvmCross.Droid.Support.V7.AppCompat;
using MvvmCross.Binding.BindingContext;

namespace YourAppName.Droid.Views.Dialogs
{
    [DialogFragment]
    public class CustomNotificationDialog : MvxDialogFragment
    {
        // 静态方法创建实例,传递弹窗需要的文本和图片资源ID
        public static CustomNotificationDialog NewInstance(string message, int imageResId)
        {
            var args = new Bundle();
            args.PutString("DialogMessage", message);
            args.PutInt("ImageResId", imageResId);
            
            var dialog = new CustomNotificationDialog();
            dialog.Arguments = args;
            return dialog;
        }

        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            base.OnCreateView(inflater, container, savedInstanceState);
            // 加载你的自定义布局
            var view = this.BindingInflate(Resource.Layout.notification, container, false);

            // 获取传递的参数
            var message = Arguments.GetString("DialogMessage");
            var imageResId = Arguments.GetInt("ImageResId");

            // 给布局中的控件赋值(根据你的notification.axml调整控件ID)
            var tvMessage = view.FindViewById<Android.Widget.TextView>(Resource.Id.tv_notification_text);
            var ivIcon = view.FindViewById<Android.Widget.ImageView>(Resource.Id.iv_notification_icon);
            
            tvMessage.Text = message;
            ivIcon.SetImageResource(imageResId);

            return view;
        }

        // 可选:设置弹窗宽度为屏幕宽度
        public override void OnStart()
        {
            base.OnStart();
            if (Dialog != null)
            {
                Dialog.Window.SetLayout(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
            }
        }
    }
}

2. 抽象弹窗服务接口(Core项目)

为了符合MVVM的跨平台原则,在Core项目中创建一个接口ICustomDialogService.cs:

namespace YourAppName.Core.Services
{
    public interface ICustomDialogService
    {
        void ShowCustomNotification(string message, int imageResourceId);
    }
}

3. 实现Android平台的弹窗服务(Android项目)

新建CustomDialogService.cs,实现上面的接口:

using YourAppName.Core.Services;
using YourAppName.Droid.Views.Dialogs;
using Android.Support.V4.App;
using MvvmCross.Platforms.Android.Views;

namespace YourAppName.Droid.Services
{
    public class CustomDialogService : ICustomDialogService
    {
        public void ShowCustomNotification(string message, int imageResourceId)
        {
            // 获取当前的顶层Activity
            var currentActivity = Mvx.IoCProvider.Resolve<IMvxAndroidCurrentTopActivity>().Activity;
            var fragmentManager = (currentActivity as FragmentActivity)?.SupportFragmentManager;

            if (fragmentManager != null)
            {
                var dialog = CustomNotificationDialog.NewInstance(message, imageResourceId);
                dialog.Show(fragmentManager, "CustomNotificationDialog");
            }
        }
    }
}

4. 注册自定义弹窗服务(Android项目Setup类)

回到Setup.cs的InitializePlatformServices方法,添加服务注册:

protected override void InitializePlatformServices()
{
    base.InitializePlatformServices();
    Mvx.IoCProvider.RegisterSingleton<IUserDialogs>(UserDialogs.Instance);
    // 注册自定义弹窗服务
    Mvx.IoCProvider.RegisterSingleton<ICustomDialogService>(new CustomDialogService());
}

5. 在ViewModel中调用自定义弹窗

在你的ViewModel中注入ICustomDialogService,并创建命令触发弹窗:

using MvvmCross.ViewModels;
using YourAppName.Core.Services;
using System.Windows.Input;
using MvvmCross.Commands;

namespace YourAppName.Core.ViewModels
{
    public class YourViewModel : MvxViewModel
    {
        private readonly ICustomDialogService _customDialogService;

        public ICommand ShowCustomNotificationCommand { get; }

        public YourViewModel(ICustomDialogService customDialogService)
        {
            _customDialogService = customDialogService;
            
            ShowCustomNotificationCommand = new MvxCommand(() =>
            {
                // 调用自定义弹窗,这里的图片资源ID是Android项目中的Drawable资源ID
                _customDialogService.ShowCustomNotification("这是自定义通知的内容", Resource.Drawable.ic_notification_icon);
            });
        }
    }
}

最后,在对应的View布局中,给按钮绑定这个命令:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="显示自定义通知"
    local:MvxBind="Click ShowCustomNotificationCommand" />

内容的提问来源于stack exchange,提问作者NaSt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:05:22