MAUI Community Toolkit跨ViewModel弹窗显示失败问题求助
问题描述
我想从ViewModel中显示一个Community Toolkit弹窗,是可以传入字符串消息的消息框。我按照文档构建了弹窗,也完成了和ViewModel的数据绑定,但在另一个ViewModel中显示该弹窗时遇到了问题。
Popup XAML代码
<ctm:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:ctm="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:vwmod="clr-namespace:LockAndKeyMaui.ViewModels" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="LockAndKeyMaui.MsgBox" x:DataType="vwmod:MsgViewModel" CanBeDismissedByTappingOutsideOfPopup="False"> <VerticalStackLayout WidthRequest="300" HeightRequest="200" BackgroundColor="Blue"> <Label Text="{Binding Msg}" TextColor="Yellow" VerticalOptions="Center" HorizontalOptions="Center" /> </VerticalStackLayout> </ctm:Popup>
Popup 后台C#代码
using CommunityToolkit.Maui.Views; using LockAndKeyMaui.ViewModels; namespace LockAndKeyMaui; public partial class MsgBox : Popup { readonly string MsgTxt; public MsgBox(MsgViewModel msgvw) { InitializeComponent(); BindingContext = msgvw; } }
Popup ViewModel代码
using CommunityToolkit.Maui.Core; using System.ComponentModel; namespace LockAndKeyMaui.ViewModels { public class MsgViewModel : INotifyPropertyChanged { private string? msg; readonly IPopupService popupService; public string Msg { get => msg!; set { msg = value; OnPropChg(nameof(Msg)); } } public MsgViewModel(IPopupService popupService) { this.popupService = popupService; } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropChg(string prName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prName)); } } }
遇到的具体问题
我尝试用以下代码显示弹窗:
this.popupService.ShowPopup<MsgViewModel>(onPresenting: viewModel => viewModel.Msg = "This is a test.");
但编译器提示Msg变量不存在。我已经在MauiProgram.cs里注册了服务:builder.Services.AddTransient<MsgBox, MsgViewModel>();,请问哪里出错了?
解决方案
1. 修正服务注册方式
你当前的服务注册写法错误,AddTransient<MsgBox, MsgViewModel>()的泛型参数要求第二个类型是第一个类型的实现类,但MsgBox和MsgViewModel并无继承/实现关系。正确的注册方式是分别注册弹窗视图和ViewModel:
// 注册弹窗视图 builder.Services.AddTransient<MsgBox>(); // 注册弹窗ViewModel builder.Services.AddTransient<MsgViewModel>();
同时确保已在MauiProgram.cs中启用Community Toolkit:
builder.UseMauiCommunityToolkit();
2. 修正ShowPopup方法的调用
ShowPopup<T>中的T必须是弹窗视图类型(即MsgBox),而非ViewModel类型。你可以通过两种方式正确调用:
- 方式一:先判断ViewModel类型再赋值
this.popupService.ShowPopup<MsgBox>(onPresenting: viewModel => { if (viewModel is MsgViewModel msgVm) { msgVm.Msg = "This is a test."; } });
- 方式二:指定弹窗视图和ViewModel的泛型参数
this.popupService.ShowPopup<MsgBox, MsgViewModel>(viewModel => viewModel.Msg = "This is a test.");
可选优化
如果MsgViewModel中的IPopupService仅用于自身调用弹窗,但你实际是从其他ViewModel触发弹窗,那么可以移除这个依赖,简化ViewModel:
// 修改后的MsgViewModel构造函数 public MsgViewModel() { }
内容的提问来源于stack exchange,提问作者Bob Gatto
相关产品推荐
相关产品推荐

