1

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>
2

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this is the most elegant solution I think. I actually got my question a bit wrong. I actually needed the ResolvedSourcePropertyName of the BindingExpression on the AnswerRequired property. So I implemented your solution with that.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.