I am adding a new Button with functionality to a large existing WPF client application. The Button Command
should fire a method on the view model through a DelegateCommand<T>
. The problem is that the whole application crashes on start, apparently because of this DelegateCommand<T>
. My code is as follows.
BaseFormViewModel (inherited by 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}"/>
Now the application is crashing on start and the interesting part of the stack trace is as follows (I have anonymized customer names and terms). Sorry for the small sized image.
I am quite new to both WPF and MVVM, so it's a bit of a learning curve for me. But from what I understand, it is complaining about the second parameter of the DelegateCommand<T>
which is the CanExecute
method. But DelegateCommand<T>
also has a constructor which only takes one parameter - the Execute
method. So why is it complaining over this?
I have tried also passing in a CanExecute
method which just returns true. But the application is still crashing with the same error.
This same use of DelegateCommand<T>
is existing several places in the application with the same syntax and signature with no problems. So this really shouldn't be an issue.
I have also tried using an ICommand
and having the ExecuteAddFileCommand
without parameters. This works for me, but is obviously not a solution as I need to pass a DocumentType
.
Can someone please help me get further towards a solution?
CodePudding user response:
I suspect that the command parameter is something else than a DocumentType
object.
If you change the type of the command to DelegateCommand<object>
you should avoid getting the exception.
Then you could put a breakpoint in your ExecuteAddFileCommand
method to determine the actual type of the parameter and whether it has been set at all. If not, check your DocumentType
source property that you bind the CommandParameter
to:
CommandParameter="{Binding DocumentType}"
It's type must match the type argument of the DelegateCommand<T>
.
CodePudding user response:
So I looked further into this today, going with @mm8's theory that my CommandParameter
was not of type DocumentType
. So I followed the DocumentType
all the way through and found that some places it was nullable, and other places it was not. And once I changed my CommandParameter
to type DocumentType?
, the application stopped crashing. My incoming parameter in ExecuteAddFileCommand()
was still null
though. And that was ofcourse because I had to include the parameter in the DelegateCommand<T>
. So the working code looks like this.
BaseFormViewModel (inherited by 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...
}