nmrlqa4
nmrlqa4

Reputation: 679

How to pass the sender and the arguments of event to the invoked command in ViewModel

In my UWP Windows 10 app I want to clean my code-behind from events and other stuff and do everything in the ViewModel, so I use Core:InvokeCommandAction to invoke a command in the VM, but I don't know how to pass it the sender and the arguments for the Navigated event of the Frame object

<Frame x:Name="MyFrame" SourcePageType="{Binding MainFramePageType, Mode=TwoWay}">
    <Interactivity:Interaction.Behaviors>
        <Core:EventTriggerBehavior EventName="Navigated">
            <Core:InvokeCommandAction Command="{Binding MyFrameNavigatedCommand}" CommandParameter="{Binding ElementName=MyFrame}"/>            
        </Core:EventTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</Frame>

in the VM:

public RelayCommand<object> MyFrameNavigatedCommand { get; private set; }

...
MyFrameNavigatedCommand = new RelayCommand<object>(MyNavigatedCommandExecuted);
...

private void MyNavigatedCommandExecuted(object sender)
{
    (sender as Frame).BackStack.Clear();
}

Upvotes: 1

Views: 2552

Answers (1)

Decade Moon
Decade Moon

Reputation: 34286

EventTriggerBehavior passes the EventArgs object to each action, so for an InvokeCommandAction you just need the bound command to accept the parameter in your command implementation. I'm not 100% familiar with MVVMLight, but you're probably using some sort of "delegate command" implementation; just make sure your delegate has a parameter and you're all good.

If you need the sender argument too, then that's probably an indication that you should not be doing whatever it is you need to do with it in the view model (accessing/modifying the view directly is not the role of the view model). Nevertheless, it is possible to pass the sender argument too if you use x:Bind to bind the event to your view model instead of EventTriggerBehavior (x:Bind requires anniversary update SDK).

XAML

<Frame x:Name="MyFrame"
       SourcePageType="{Binding MainFramePageType, Mode=TwoWay}"
       Navigated="{x:Bind Vm.Navigated}"/>

Code behind

public MyViewModel Vm => (MyViewModel)DataContext;

View model

public void Navigated(object sender, NavigationEventArgs e)
{
}

Alternatively you can keep what you have already but just expose a Frame property on your view model which you can set in your page's code behind.

Based on the code you provided, if all you want to do is to clear the frame's back stack (or whatever) when the frame has navigated, then you can put this into your own custom behavior or attached property to handle view-specific things instead.

Upvotes: 1

Related Questions