命令MVVM中的NullReference

时间:2017-01-25 11:57:37

标签: c# wpf mvvm command

我正在开发一个使用MVVM设计模式的应用程序。但是我很难将viewmodel中的命令绑定到视图。 这是我的代码:

我有一个名为 Part

的模型
 public class Part
 {
    private string _partcode;
    private string _description;

    public string PartCode
    {
        get { return _partcode.Trim(); }
        set { _partcode = value; }
    }

    public string Description
    {
        get { return _description; }
        set { _description = value; }
    }
  }

带有命令的ViewModel,名为 PartViewModel

    /// <summary>
    /// Returns a ViewModel containing all parts.
    /// </summary>
    /// <param name="dt">Database to use.</param>
    public PartViewModel(DatabaseType dt)
    {
        GenerateViewModelForAllParts(dt);
    }
    private async void GenerateViewModelForAllParts(DatabaseType dt)
    {
        using (NexusWCFServiceClient client = new NexusWCFServiceClient())
            foreach (Part item in await client.GetAllPartsAsync(dt))
                _items.Add(item);
    }
    #endregion

    #region Members
    private ObservableCollection<Part> _items = new ObservableCollection<Part>();

    private Part _part;
    int count = 0;
    #endregion

    #region Properties
    public ObservableCollection<Part> Items
    {
        get { return _items; }
        set { _items = value; }
    }

    public Part Part
    {
        get { return _part; }
        set { _part = value; }
    }

    public string PartCode
    {
        get { return Part.PartCode; }
        set
        {
            if (Part.PartCode != value) /* Check if value is changed */
            {
                Part.PartCode = value;
                RaisePropertyChanged("PartCode");  /* Raise event */
            }
        }
    }

    public string Description
    {
        get { return Part.Description; }
        set
        {
            if (Part.Description != value)
            {
                Part.Description = value;
                RaisePropertyChanged("Description");
            }
        }
    }

    public ICommand UpdateDescription
    {
        get
        {
            return new RelayCommand(UpdateDescriptionExecute, CanUpdateDescriptionExecute);
        }
    }
    #endregion
}

还有一些辅助类:

ObservableObject

public class ObservableObject : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region Methods
    public void RaisePropertyChanged(string propertyname)
    {
        PropertyChangedEventHandler handler = PropertyChanged;             // Create a new instance to prevent thread issues
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyname));
        }
    }
    #endregion
}

RelayCommand

public class RelayCommand : ICommand
{
    #region Members
    private bool _canExec = true;
    readonly Func<bool> _canExecute;
    readonly Action _execute;
    public event EventHandler CanExecuteChanged;
    #endregion

    #region Constructors
    public RelayCommand(Action execute) : this(execute, null)
    {

    }

    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion

    public bool CanExecute(object parameter)
    {
        bool previousCanExec = _canExec;
        _canExec = _canExecute == null ? true : _canExecute();
        if (previousCanExec != _canExec)
        {
            CanExecuteChanged(parameter, null);
        }
        return _canExec;
    }

    public void Execute(object parameter)
    {
        _execute();
        CanExecute(null);
    }
}

在我的MainWindow中,我通过以下方式设置DataContext:

base.DataContext = new PartViewModel("TPGC070", DatabaseType.TestDB);

返回包含give参数的所有部分。好的,直到现在。

在我的 MainWindow 中,我在列表视图中显示了viewmodel:

<Window x:Class="NexusWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="700" Width="525" x:Name="TestBinding">
    <Grid>
        <StackPanel x:Name="stck">
            <ListView x:Name="lb" ItemsSource="{Binding Items}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical" x:Name="stck">
                            <TextBlock Text="{Binding Path=PartCode}"/>
                            <TextBlock Text="{Binding Path=Description}"/>
                            <Button Content="Update" DataContext="{Binding ElementName=TestBinding, Path=DataContext}" Command="{Binding UpdateDescription}" CommandParameter="{Binding ElementName=lb, Path=DataContext}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

            <StackPanel x:Name="sp" DataContext="{Binding ElementName=lb, Path=SelectedItem}">
                <Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.UpdateDescription}" Content="Update Description"/>
                <TextBlock Text="{Binding Path=Description}"/>
            </StackPanel>

        </StackPanel>
    </Grid>
</Window>

所以我正在尝试的是两件事。我希望listview中的命令更新集合中所选项的描述。它确实找到了命令,但我在viewmodel中的描述中得到以下错误:

An unhandled exception of type 'System.NullReferenceException' occurred in ...

我还尝试创建一个stackpanel,它保存listview的所选项目,然后尝试更新描述。这里会弹出相同的错误。

它尝试了几种绑定语法,但它们都没有工作。我现在使用的那些确实找到了命令,但我在描述中得到了NullReference错误。 我感觉命令和集合并没有彼此绑定,但我似乎无法找出原因。

我在搜索SO时遇到了同样的错误,但似乎无法找到一个处理我的架构所用逻辑的好解决方案。也许它在根或只是一个简单的绑定问题。这就是为什么我不认为它是重复的。

我错过了一些明显的东西吗?任何帮助将不胜感激。

0 个答案:

没有答案