Smedegaard
Smedegaard

Reputation: 788

Passing both Source and Property with InvokeCommandAction, without using MultiBindings

Introduction to the problem

I have a binding in XAML on a property in my view model, called "IsYoungerThanSeventy". Iøm using Prism to call a command on the event TargetUpdated. At the moment I'm passing Source (the BinaryQuestion) using TriggerParameterPath="Source".

The problem

I can't pass both Source and Property

What I want to do

I'd like to also pass the Property (IsYoungerThanSeventy) to the same command.

Ultimatly I need both the Source and Property in a function I'm calling to update stuff.

My code so far

<wpfQuestionnaire:BinaryQuestion
    AnswerRequired="{Binding IsYoungerThanSeventy
        , Mode=TwoWay                                          
        , NotifyOnTargetUpdated=True}">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="TargetUpdated">
            <prism:InvokeCommandAction 
                Command="{Binding PropertyBoundToAnswerRequiredChangedCommand}"
                TriggerParameterPath="Source"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</wpfQuestionnaire:BinaryQuestion>

Upvotes: 1

Views: 825

Answers (2)

Bertrand
Bertrand

Reputation: 59

Have you tried passing no argument?

<i:Interaction.Triggers>
    <i:EventTrigger EventName="TargetUpdated">
        <prism:InvokeCommandAction 
            Command="{Binding PropertyBoundToAnswerRequiredChangedCommand}"
            />
    </i:EventTrigger>
</i:Interaction.Triggers>

Then your command can be declared

PropertyBoundToAnswerRequiredChangedCommand = new DelegateCommand<DataTransferEventArgs>(OnPropertyBoundToAnswerRequiredChanged);

with

public void OnPropertyBoundToAnswerRequiredChanged(DataTransferEventArgs e){
var isYoungerThanSeventy = e.Property as bool;
var source = e.Source;
}

and you can use both.

Upvotes: 0

mm8
mm8

Reputation: 169200

The Execute method of the ICommand interface accepts only a single parameter so for you to be able to pass two values you need to create a type that can hold these two values and then pass an instance of this type as the command parameter to the command.

The easiest way to do this would be to invoke the command from the code-behind of the view and create an instance of your custom type in here, e.g.:

<wpfQuestionnaire:BinaryQuestion
    AnswerRequired="{Binding IsYoungerThanSeventy
        , Mode=TwoWay                                          
        , NotifyOnTargetUpdated=True}" TargetUpdated="BinaryQuestion_TargetUpdated">
</wpfQuestionnaire:BinaryQuestion>

private void BinaryQuestion_TargetUpdated(object sender, DataTransferEventArgs e)
{
    BinaryQuestion bq = sender as BinaryQuestion;
    ViewModel vm = bq.DataContext as ViewModel;
    if (vm != null)
    {
        YourCustomCompositeCommandArgumentType param = new YourCustomCompositeCommandArgumentType() { Source = bq, Parameter = vm.IsYoungerThanSeventy };
        vm.PropertyBoundToAnswerRequiredChangedCommand.Execute(param);
    }
}

This doesn't break the MVVM pattern since you are just invoking the very same command from the very same view. MVVM is not about eliminating code from the view, it is about separation of concerns.

If you refuse to implement view-related behaviour in the code-behind for some strange reason you will have to wrap the functionality in a custom InvokeCommandAction class. You could add properties to this class that hold your source and property values and then invoked the command as I explained in the above sample code.

Upvotes: 1

Related Questions