DelegateCommand<T> 对象引用未设置为对象的实例

DelegateCommand<T> Object reference not set to an instance of an object

我正在向现有的大型 WPF 客户端应用程序添加一个具有功能的新按钮。 Button Command 应该通过 DelegateCommand<T> 在视图模型上触发一个方法。问题是整个应用程序在启动时崩溃,显然是因为 DelegateCommand<T>。我的代码如下。

BaseFormViewModel(由PensionTakerViewModel继承)

public DelegateCommand<DocumentType> AddFileCommand { get; private set; }

public BaseFormViewModel(...)
{
    this.AddFileCommand = new DelegateCommand<DocumentType>(this.ExecuteAddFileCommand);
}

protected virtual void ExecuteAddFileCommand(DocumentType documentType)
{
  // Do something...
}

PensionTakerView

<ctrl:ErrorDecorator Grid.Row="1" Grid.Column="0">
    <ComboBox AutomationProperties.AutomationId="cmbDocumentType" 
              ItemsSource="{Binding ViewModel.DocumentTypes, ElementName=Root}" 
              DisplayMemberPath="Name" 
              SelectedValuePath="Value"
              SelectedValue="{Binding DocumentType}"/>
</ctrl:ErrorDecorator>
                
<Button Grid.Row="1" Grid.Column="2" Content="Tilføj fil" 
        Command="{Binding ViewModel.AddFileCommand, ElementName=Root}"
        CommandParameter="{Binding DocumentType}"/>

现在应用程序在启动时崩溃,堆栈跟踪中有趣的部分如下(我匿名了客户名称和术语)。对不起,小尺寸的图像。

我对 WPF 和 MVVM 都很陌生,所以这对我来说有点学习曲线。但据我了解,它是在抱怨 DelegateCommand<T> 的第二个参数,即 CanExecute 方法。但是 DelegateCommand<T> 也有一个只接受一个参数的构造函数 - Execute 方法。那它为什么要抱怨这个呢?

我也试过传递一个 CanExecute 方法,它只是 returns 正确。但是应用程序仍然因同样的错误而崩溃。

DelegateCommand<T> 的相同用法存在于应用程序中的多个位置,具有相同的语法和签名,没有问题。所以这真的不应该成为问题。

我也尝试过使用 ICommand 和不带参数的 ExecuteAddFileCommand。这对我有用,但显然不是解决方案,因为我需要传递 DocumentType.

有人可以帮助我进一步解决问题吗?

我怀疑命令参数不是 DocumentType 对象。

如果将命令类型更改为 DelegateCommand<object>,则应避免出现异常。

然后你可以在你的 ExecuteAddFileCommand 方法中放置一个断点来确定参数的实际类型以及它是否已经被设置。如果不是,请检查您的 DocumentType 来源 属性,您将 CommandParameter 绑定到:

CommandParameter="{Binding DocumentType}"

它的类型必须与 DelegateCommand<T> 的类型参数相匹配。

所以我今天进一步研究了这个,根据@mm8 的理论,我的 CommandParameter 不是 DocumentType 类型。于是我一路跟着DocumentType,发现有的地方可以为空,有的地方不可以。一旦我将 CommandParameter 更改为键入 DocumentType?,应用程序就不再崩溃了。我在 ExecuteAddFileCommand() 中的传入参数仍然是 null。这当然是因为我必须在 DelegateCommand<T> 中包含参数。所以工作代码看起来像这样。

BaseFormViewModel(由PensionTakerViewModel继承)

public DelegateCommand<DocumentType?> AddFileCommand { get; private set; }

public BaseFormViewModel(...)
{
    this.AddFileCommand = new DelegateCommand<DocumentType?>(param => this.ExecuteAddFileCommand(param));
}

protected virtual void ExecuteAddFileCommand(DocumentType? documentType)
{
  // Do something...
}