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

Xamarin中InitializeComponent()触发NullReferenceException问题求助

问题:Xamarin MVVM模式下InitializeComponent()触发NullReferenceException

我是Xamarin新手,尝试通过MVVM模式读取Editor/Entry的值,但每次启动代码打开页面时,InitializeComponent()都会触发NullReferenceException。我已将Editor的Text绑定到ViewModel中的属性,并在XAML中引用了命名空间,查阅文档及示例代码后仍无法解决问题,附上相关代码,恳请帮忙排查。


XAML代码

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:student_app.ViewModels"
             x:Class="student_app.Views.AddCategoryPage"
             xmlns:model="clr-namespace:student_app.Models" >
    <ContentPage.BindingContext>
        <local:AddCategoryViewModel/>
    </ContentPage.BindingContext>

    <RefreshView x:DataType="local:AddCategoryViewModel" Command="{Binding LoadCategoriesCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
        <StackLayout>
            <Label Text="Add Category:"/>
            <Editor Grid.Row="1" Grid.Column="0" Width="300" Text="{Binding CategoryNameEditor}" Placeholder="enter category name"/>
            <Button x:Name="saveButton" Text="Save" Command="{Binding SaveCommand}"/>
        </StackLayout>
    </RefreshView>
</ContentPage>

页面后台代码

namespace student_app.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class AddCategoryPage : ContentPage
    {
        AddCategoryViewModel _viewModel;
        public AddCategoryPage()
        {
            InitializeComponent();
            this.BindingContext = _viewModel = AppContainer.Resolve<AddCategoryViewModel>();
        }


        protected override void OnAppearing()
        {
            base.OnAppearing();
            _viewModel.OnAppearing();
        }
    }
}

ViewModel代码

namespace student_app.ViewModels
{
    public class AddCategoryViewModel : BaseViewModel
    {
        private readonly IToastService _toastService;
        private readonly INavigationService _navigationService;
        private readonly ICategoryService _categoryService;
        public string categoryName;

       
        public Command SaveCommand { get; }
        public Command LoadCategoriesCommand { get; }
        public event PropertyChangingEventHandler PropertyChanged;

        public string CategoryNameEditor 
        {
            get => categoryName;

            set
            {
                categoryName = value;
                var args = new PropertyChangingEventArgs(nameof(CategoryNameEditor));
                PropertyChanged?.Invoke(this, args);
            }
        }
        public AddCategoryViewModel(IToastService toastService, INavigationService navigationService, ICategoryService categoryService)
        {
            _toastService = toastService;
            _navigationService = navigationService;
            _categoryService = categoryService;
            SaveCommand = new Command(async () => await ExecuteSaveCommandCommand());
            LoadCategoriesCommand = new Command(async () => await ExecuteLoadCategoriesCommand());
        }

        public async Task ExecuteLoadCategoriesCommand()
        {
            IsBusy = true;
            try
            {
                categoryName = string.Empty;
            }
            catch (Exception ex)
            {
                await _toastService.DisplayToastAsync(ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }


        public async Task ExecuteSaveCommandCommand()
        {
            IsBusy = true;
            try
            {
                _categoryService.addCategory(categoryName);
                categoryName = string.Empty;
                await _navigationService.NavigateAsync("CalanderPage");
            }
            catch (Exception ex)
            {
                await _toastService.DisplayToastAsync(ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }
        public void OnAppearing()
        {
            IsBusy = true;
        }

    }
}

问题排查与解决方案

1. BindingContext重复设置导致初始化失败

XAML中通过<ContentPage.BindingContext>尝试创建AddCategoryViewModel实例,但你的ViewModel仅提供了带三个依赖参数的构造函数,无参构造函数不存在,XAML初始化时无法创建实例,直接抛出NullReferenceException。同时后台代码又通过依赖注入重新设置了BindingContext,属于重复操作。
解决:删除XAML中的<ContentPage.BindingContext>节点,保留后台依赖注入的逻辑。

2. PropertyChanged事件类型错误

ViewModel中错误声明了PropertyChangingEventHandler类型的PropertyChanged事件,正确的应该是PropertyChangedEventHandler,且触发时需传入PropertyChangedEventArgs。如果继承的BaseViewModel已经实现了INotifyPropertyChanged接口,直接调用基类的OnPropertyChanged方法即可,无需自行声明事件。
修正示例:

// 移除自行声明的PropertyChanged事件,使用基类实现
public string CategoryNameEditor 
{
    get => categoryName;
    set
    {
        categoryName = value;
        OnPropertyChanged(nameof(CategoryNameEditor));
    }
}

3. 无效的布局属性

Editor控件设置了Grid.Row和Grid.Column属性,但它的父容器是StackLayout,这些属性不会生效,属于无效代码,建议移除。

4. 直接赋值字段未触发属性变更

在ExecuteLoadCategoriesCommand和ExecuteSaveCommandCommand中直接给categoryName字段赋值,不会触发PropertyChanged事件,导致UI无法同步更新。应改为给CategoryNameEditor属性赋值:

// 替换 categoryName = string.Empty;
CategoryNameEditor = string.Empty;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:36:16