c# - '类型' System.NullReferenceException'的未处理异常

时间:2017-09-17 07:29:57

标签: c# wpf mvvm

我是MVVM中的新手,我有一个Model.cs,其中包含一些' ID'和' PositionName'我得到View.cs,其中包含DataGrid,其中包含SelectedItems = {Binding Items}和ItemSource = {Binding Position},以及一个带有Command = {Binding SHOWEdits}的按钮,点击后我在'Items.PositionName遇到NullReference错误== null'。
这是我的代码。

ViewModel.cs

class PositionVM : INotifyPropertyChanged
{
    private ObservableCollection<PositionModel> _position;
    private PositionModel _items;
    private ICommand _showedits;
    public ObservableCollection<PositionModel> Position
    {
        get
        {
            return _position;
        }
        set
        {
            _position = value;
            NotifyProperty("Position");
        }
    }
    public PositionModel Items
    {
        get
        {
            return _items;
        }
        set
        {
            _items = value;
            NotifyProperty("Items");
        }
    }
    public ICommand ShowEdits
    {
        get
        {
            if (_showedits == null)
                _showedits = new ShowEdit();
            return _showedits;
        }
        set
        {
            _showedits = value;
        }
    }
    public PositionVM()
    {
        Position = new ObservableCollection<PositionModel>();
        Position.Add(new PositionModel()
        {
            ID = 1,
            PositionName = "asd"
        });
    }
    public void ShowEditDialog()
    {
        if (Items.PositionName == null)
        {
            MessageBox.Show("ERROR");
        }
        else
        {
            PositionView view = new PositionView();
            Data.ID = view.txtid.Text;
            var z = new PositionView();
            z.ShowDialog();
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyProperty(String info)
    {
        if(PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

为什么我收到此错误?我该如何避免呢? Thanksss

2 个答案:

答案 0 :(得分:0)

此行

Items.PositionName == null

抛出空引用异常,很明显Items为空。

为什么Items为空?

Items属性定义如下:

public PositionModel Items
{
    get
    {
        return _items;
    }
    set
    {
        _items = value;
        NotifyProperty("Items");
    }
}

当您尝试设置PositionModel的值时,对getter(get { return _items; })的调用已完成,以便您获得_items指向的对象的引用。你得到的值是null。这意味着要么没有调用setter,要么使用值初始化_items,要么已经初始化,但稍后代码的另一部分已将其设置为null。

查看代码,我们会看到您班级的构造函数:

public PositionVM()
{
    Position = new ObservableCollection<PositionModel>();
    Position.Add(new PositionModel()
    {
        ID = 1,
        PositionName = "asd"
    });
}

显然,Items未在那里初始化。因此Items具有引用类型的默认值,null ...

答案 1 :(得分:0)

我认为您的ICommand问题。尝试将其作为财产:

public ICommand ShowEditsCommand { get; set; };

当然,你需要创造它。我使用我的Command类,你也可以在第一次使用它,它非常简单:

/// <summary>
/// Relay implementation of ICommand.
/// </summary>
public class RelayCommand : ICommand
{
    private Action execute;

    private Predicate<object> canExecute;

    private event EventHandler CanExecuteChangedInternal;

    public RelayCommand(Action execute)
        : this(execute, DefaultCanExecute)
    {
    }

    public RelayCommand(Action execute, Predicate<object> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        if (canExecute == null)
        {
            throw new ArgumentNullException("canExecute");
        }

        this.execute = execute;
        this.canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
            this.CanExecuteChangedInternal += value;
        }

        remove
        {
            CommandManager.RequerySuggested -= value;
            this.CanExecuteChangedInternal -= value;
        }
    }

    public bool CanExecute(object parameter)
    {
        return this.canExecute != null && this.canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        this.execute();
    }

    public void OnCanExecuteChanged()
    {
        EventHandler handler = this.CanExecuteChangedInternal;
        if (handler != null)
        {
            handler.Invoke(this, EventArgs.Empty);
        }
    }

    public void Destroy()
    {
        this.canExecute = _ => false;
        this.execute = () => { return; };
    }

    private static bool DefaultCanExecute(object parameter)
    {
        return true;
    }
}

在此之后,您需要在viewmodel构造函数中初始化它并将其绑定到方法:

ShowEditsCommand = new RelayCommand(ShowEdits);

ShowEdits是您在命令调用时需要运行的方法:

public void ShowEdits()
{
 // do something here
}