Ошибка нулевой ссылки в приложении App.xaml MVVM light - PullRequest
0 голосов
/ 02 января 2019

Я сделаю приложение WPF с одним окном и, изменив содержимое Frame, переместюсь через мое приложение. Для этого я использую MVVM light.

Но на App.xaml Я получил эту ошибку в списке ошибок Visual Studio.

Ссылка на объект не установлена ​​для экземпляра объекта.

Вот код, где происходит ошибка:

<Application 
    x:Class="Project.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Project" 
    StartupUri="MainWindow.xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    d1p1:Ignorable="d" 
    xmlns:vm="clr-namespace:Project.ViewModel"
    xmlns:services="clr-namespace:Project.Services"
    xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <Application.Resources>
        <ResourceDictionary>
            <services:IocContainer x:Key="ioc" />
            <vm:ApplicationViewModel x:Key="appvm" d:IsDataSource="True" /> <!-- error happens on this line -->
        </ResourceDictionary>
    </Application.Resources>
</Application>

Это мой MainWindow:

<Window x:Class="Project.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Project"
        mc:Ignorable="d"
        DataContext="{StaticResource appvm}"
        Title="Project" Height="450" Width="800">
    <Frame>
        <Frame.Content>
            <Page Content="{Binding CurrentPage, Mode=TwoWay}" />
        </Frame.Content>
    </Frame>
</Window>

Вот мой ApplicationViewModel, который наследуется от ViewModelBase:

public class ApplicationViewModel : ViewModelBase
{
    private Page _currentPage = IocContainer.Ioc.StartScreenPage;

    public Page CurrentPage
    {
        get
        {
            return _currentPage;
        }
        set
        {
            if (_currentPage != value)
            {
                _currentPage = value;
                OnPropertyChanged();
            }
        }
    }

    public StartScreenViewModel StartScreenViewModel
    {
        get
        {
            return (App.Current.Resources["ioc"] as IocContainer)?.StartScreenViewModel;
        }
    }

    public void Navigate(Type sourcePageType)
    {
    }
}

Вот ViewModelBase, который реализует INotifyPropertyChanged.

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            Debug.WriteLine("PropertyChanged is niet null ☺");
        }
        else
        {
            Debug.WriteLine("PropertyChanged is null");
        }
    }
}

Вот мой контейнер IoC:

public class IocContainer
{
    static IocContainer()
    {
        SimpleIoc.Default.Register<ApplicationViewModel>(false);
        SimpleIoc.Default.Register<StartScreenViewModel>(false);
        SimpleIoc.Default.Register<StartScreenPage>(false);
    }

    public static IocContainer Ioc
    {
        get { return App.Current.Resources["ioc"] as IocContainer; }
    }

    public ApplicationViewModel ApplicationViewModel
    {
        get { return SimpleIoc.Default.GetInstance<ApplicationViewModel>(); }
    }

    public StartScreenPage StartScreenPage
    {
        get { return SimpleIoc.Default.GetInstance<StartScreenPage>(); }
    }

    public StartScreenViewModel StartScreenViewModel
    {
        get { return SimpleIoc.Default.GetInstance<StartScreenViewModel>(); }
    }
}

Вот мой StartScreenPage:

<Page x:Class="Project.StartScreenPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Project"
      mc:Ignorable="d" 
      DataContext="{Binding StartScreenViewModel, Source={StaticResource ioc}}"
      Title="StartScreen">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>

        <Label Content="Hello world" Grid.Row="0" Grid.Column="0" />
    </Grid>
</Page>

А вот и StartScreenViewModel.

public class StartScreenViewModel : ViewModelBase
{ }

Все приложения, окна и страницы имеют конструктор по умолчанию, который вызывает InitializeComponent.

Я могу запустить свое приложение, но вижу пустое окно.

Я что-то забыл?

Редактировать: В продолжение моего ответа на этот вопрос: Page может иметь только Frame в качестве родителя, а не Window, я изменил свой код MainWindow на это:

Код на MainWindow должен быть таким:

<!-- Opening Window tag with all attributes -->
<Frame Content="{Binding CurrentPage, Mode=TwoWay}" />
<!-- Closing Window tag -->

Это также покажет StartScreenPage в окне.

Однако ошибка нулевой ссылки все еще генерируется.

1 Ответ

0 голосов
/ 02 января 2019

В вашем коде очень мало нулевой проверки, и именно здесь это происходит.

Лучший способ найти проблему - перейти на панель инструментов Visual Studio

Debug & rarr; Windows & rarr; Настройки исключений

и полностью проверьте строку, помеченную 'Common Language Runtime Exceptions'. Когда вы снова запустите код, вы должны получить больше информации о том, где происходит исключение NULL.

...