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

.NET MAUI集成Xamarin.Forms代码时遇CS0311错误求助

问题描述

将Xamarin.Forms聊天应用代码适配到.NET 7的.NET MAUI项目时,所有页面触发CS0311编译错误,错误信息如下:

error CS0311: The type 'MauiApp1.Views.CallPage' cannot be used as type parameter 'TView' in the generic type or method 'IContainerRegistryExtensions.RegisterForNavigation<TView, TViewModel>(IContainerRegistry, string)'. There is no implicit reference conversion from 'MauiApp1.Views.CallPage' to 'Xamarin.Forms.Page'.

相关代码片段:

App类代码

using MauiApp1.Services.Core;
using MauiApp1.Services.Interfaces;
using MauiApp1.ViewModels;
using MauiApp1.Views;
using Prism;
using Prism.Ioc;
using Prism.Unity; 

namespace MauiApp1
{
    public partial class App : PrismApplication 
    {
        public App(IPlatformInitializer initializer = null) : base(initializer) 
        {

        }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            await NavigationService.NavigateAsync("NavigationPage/MainPage");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
            containerRegistry.RegisterForNavigation<ChatRoomPage, ChatRoomPageViewModel>();
            containerRegistry.RegisterForNavigation<FriendsPage, FriendsPageViewModel>();
            containerRegistry.Register<IChatService, ChatService>();
            containerRegistry.Register<IAuthenticationService, AuthenticationService>();
            containerRegistry.Register<ISessionService, SessionService>();
            containerRegistry.Register<IUsersService, UsersService>();
            containerRegistry.RegisterForNavigation<PrivateChatPage, PrivateChatPageViewModel>();
            containerRegistry.RegisterForNavigation<IncomeCallPage, IncomeCallPageViewModel>();
            containerRegistry.RegisterForNavigation<CallPage, CallPageViewModel>();
        }
    }
}

CallPage的XAML代码

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp1.Views.CallPage"
             xmlns:prism="http://prismlibrary.com" 
             xmlns:views="clr-namespace:MauiApp1.Views"
             Title="CallPage">
    <Grid RowDefinitions="50,*,60,30">
        <views:GenericWebView x:Name="CallWebView"       
                 Grid.RowSpan="4"/>
             <!--prism:ViewModelLocator.AutowireViewModel="True"-->
        <!--<RelativeLayout VerticalOptions="FillAndExpand" 
                 HorizontalOptions="FillAndExpand"
                 BackgroundColor="#CCC"
                 Grid.RowSpan="4"
                 IsVisible="false"/>
        <Frame Margin="0"
               Padding="0"
               IsVisible="false">
            <Grid ColumnDefinitions="*, 50,50">
                <Label VerticalOptions="Center"
                   Text="Someone is calling..."
                   Padding="0"
                   Margin="10,0,0,0"/>
                <Image Grid.Column="1"
                       HeightRequest="25"
                       VerticalOptions="Center"
                       Source="outline_call.png"/>
                <Image Grid.Column="2"
                       HeightRequest="25"
                       VerticalOptions="Center"
                       Source="end_call.png"/>
            </Grid>
        </Frame>
        <StackLayout Grid.Row="2"
                     Margin="0,0,10,0"
                     Orientation="Horizontal"
                     HorizontalOptions="Center"
                     BackgroundColor="Transparent">
            <Frame HasShadow="True"
                   CornerRadius="50"
                   HeightRequest="60"
                   WidthRequest="60"
                   Padding="1"
                   BackgroundColor="{Binding IsAudioActive, Converter={StaticResource BooleanToColorConverter}, ConverterParameter=#00FFFFFF|#80CCCCCC}"
                   BorderColor="LightGray"
                   HorizontalOptions="Start"
                   VerticalOptions="Center">
                <ImageButton Source="mic_off.png"
                             Margin="10"
                             CornerRadius="50"
                             HeightRequest="50"
                             WidthRequest="50"
                             HorizontalOptions="Center"
                             BackgroundColor="Transparent"
                             Clicked="ToggleMicClick"/>
            </Frame>
            <Frame HasShadow="True"
                   CornerRadius="50"
                   HeightRequest="60"
                   WidthRequest="60"
                   Padding="1"
                   BackgroundColor="#CC0000"
                   BorderColor="LightGray"
                   HorizontalOptions="Center"
                   VerticalOptions="Center">
                <ImageButton Source="end_call.png"
                             Margin="10"
                             CornerRadius="50"
                             HeightRequest="50"
                             WidthRequest="50"
                             HorizontalOptions="Center"
                             BackgroundColor="Transparent"
                             Clicked="EndCallClick"
                             Command="{Binding EndCallClick}"/>
            </Frame>
            <Frame HasShadow="True"
                   CornerRadius="50"
                   HeightRequest="60"
                   WidthRequest="60"
                   Padding="1"
                   BackgroundColor="{Binding IsVideoActive, Converter={StaticResource BooleanToColorConverter}, ConverterParameter=#007E33|#80CCCCCC}"
                   BorderColor="LightGray"
                   HorizontalOptions="EndAndExpand"
                   VerticalOptions="Center">
                <ImageButton Source="video_call.png"
                             Margin="10"
                             CornerRadius="50"
                             HeightRequest="50"
                             WidthRequest="50"
                             HorizontalOptions="Center"
                             BackgroundColor="Transparent"
                             Clicked="ToggelCameraClick"/>
            </Frame>
        </StackLayout>
    </Grid>
</ContentPage>

CallPage后台代码

using MauiApp1.Services.Interfaces;
using MauiApp1.ViewModels;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace MauiApp1.Views;

public partial class CallPage
{
    private CallPageViewModel callPageViewModel;
    public CallPage()
    {
        InitializeComponent();
        var urlSource = new Microsoft.Maui.Controls.UrlWebViewSource();
        string baseUrl = Microsoft.Maui.Controls.DependencyService.Get<IWebViewService>().GetContent();
        urlSource.Url = baseUrl;
        CallWebView.Source = urlSource;
        callPageViewModel = BindingContext as CallPageViewModel;
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        await Task.Delay(1000);
        var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
        if (status != PermissionStatus.Granted)
        {
            var response = await Permissions.RequestAsync<Permissions.Camera>();
        }
        var statusMic = await Permissions.CheckStatusAsync<Permissions.Microphone>();
        if (statusMic != PermissionStatus.Granted)
        {
            var response = await Permissions.RequestAsync<Permissions.Microphone>();
        }
        await Connect();
    }

    private async Task Connect()
    {
        try
        {
            await CallWebView.EvaluateJavaScriptAsync($"init('{callPageViewModel.CurrentUser.ID}');");
            await Task.Delay(2000);
            await CallWebView.EvaluateJavaScriptAsync($"startCall('{callPageViewModel.Friend.ID}');");
        }
        catch (Exception exp) {}
    }

    private async void ToggleMicClick(object sender, EventArgs e)
    {
        callPageViewModel.IsAudioActive = !callPageViewModel.IsAudioActive;
        await CallWebView.EvaluateJavaScriptAsync($"toggleAudio('{callPageViewModel.IsAudioActive.ToString().ToLower()}');");
    }

    private void EndCallClick(object sender, EventArgs e)
    {
        EndCall();
    }

    private async void ToggelCameraClick(object sender, EventArgs e)
    {
        callPageViewModel.IsVideoActive = !callPageViewModel.IsVideoActive;
        await CallWebView.EvaluateJavaScriptAsync($"toggleVideo('{callPageViewModel.IsVideoActive.ToString().ToLower()}');");
    }

    private void EndCall()
    {
        CallWebView.Source = "about:blank";
    }
}
解决方案

错误核心原因是:MAUI页面继承自Microsoft.Maui.Controls.ContentPage,但代码中混用了Xamarin.Forms的命名空间与Prism包,导致Prism的导航注册无法识别MAUI页面类型。

1. 替换Prism依赖包

移除项目中针对Xamarin.Forms的Prism包(如Prism.Unity、Prism.Forms),安装适配MAUI的Prism.Maui NuGet包。

2. 修正页面后台代码

将页面代码中的Xamarin.Forms命名空间替换为Microsoft.Maui.Controls,并确保页面类显式继承ContentPage:

using MauiApp1.Services.Interfaces;
using MauiApp1.ViewModels;
using System;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.ApplicationModel;

namespace MauiApp1.Views;

public partial class CallPage : ContentPage
{
    private CallPageViewModel callPageViewModel;
    public CallPage()
    {
        InitializeComponent();
        var urlSource = new UrlWebViewSource();
        string baseUrl = DependencyService.Get<IWebViewService>().GetContent();
        urlSource.Url = baseUrl;
        CallWebView.Source = urlSource;
        callPageViewModel = BindingContext as CallPageViewModel;
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        await Task.Delay(1000);
        var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
        if (status != PermissionStatus.Granted)
        {
            var response = await Permissions.RequestAsync<Permissions.Camera>();
        }
        var statusMic = await Permissions.CheckStatusAsync<Permissions.Microphone>();
        if (statusMic != PermissionStatus.Granted)
        {
            var response = await Permissions.RequestAsync<Permissions.Microphone>();
        }
        await Connect();
    }

    private async Task Connect()
    {
        try
        {
            await CallWebView.EvaluateJavaScriptAsync($"init('{callPageViewModel.CurrentUser.ID}');");
            await Task.Delay(2000);
            await CallWebView.EvaluateJavaScriptAsync($"startCall('{callPageViewModel.Friend.ID}');");
        }
        catch (Exception exp) {}
    }

    private async void ToggleMicClick(object sender, EventArgs e)
    {
        callPageViewModel.IsAudioActive = !callPageViewModel.IsAudioActive;
        await CallWebView.EvaluateJavaScriptAsync($"toggleAudio('{callPageViewModel.IsAudioActive.ToString().ToLower()}');");
    }

    private void EndCallClick(object sender, EventArgs e)
    {
        EndCall();
    }

    private async void ToggelCameraClick(object sender, EventArgs e)
    {
        callPageViewModel.IsVideoActive = !callPageViewModel.IsVideoActive;
        await CallWebView.EvaluateJavaScriptAsync($"toggleVideo('{callPageViewModel.IsVideoActive.ToString().ToLower()}');");
    }

    private void EndCall()
    {
        CallWebView.Source = "about:blank";
    }
}

3. 修正App类的Prism引用

替换App类中的Prism命名空间,使用MAUI版本的Prism:

using MauiApp1.Services.Core;
using MauiApp1.Services.Interfaces;
using MauiApp1.ViewModels;
using MauiApp1.Views;
using Prism;
using Prism.Ioc;
using Prism.Maui;

namespace MauiApp1
{
    public partial class App : PrismApplication 
    {
        public App(IPlatformInitializer initializer = null) : base(initializer) 
        {
        }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            await NavigationService.NavigateAsync("NavigationPage/MainPage");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
            containerRegistry.RegisterForNavigation<ChatRoomPage, ChatRoomPageViewModel>();
            containerRegistry.RegisterForNavigation<FriendsPage, FriendsPageViewModel>();
            containerRegistry.Register<IChatService, ChatService>();
            containerRegistry.Register<IAuthenticationService, AuthenticationService>();
            containerRegistry.Register<ISessionService, SessionService>();
            containerRegistry.Register<IUsersService, UsersService>();
            containerRegistry.RegisterForNavigation<PrivateChatPage, PrivateChatPageViewModel>();
            containerRegistry.RegisterForNavigation<IncomeCallPage, IncomeCallPageViewModel>();
            containerRegistry.RegisterForNavigation<CallPage, CallPageViewModel>();
        }
    }
}

4. 全局检查命名空间

遍历所有ViewModel、服务类,移除Xamarin.Forms相关引用,替换为MAUI对应的Microsoft.Maui.*命名空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:09:55