我是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
答案 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
}