Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind an event to a command in a Universal App using the MVVM pattern?

I hope somebody can help.

I've spent some time researching the best way to bind an event to a ViewModel command using the MVVM pattern when developing a Universal App. I'm using MVVM Light. As a test I'm using the SelectionChanged event of a ComboBox.

I've read a few people that have pinched the Behaviours SDK from the Windows 8.1 / WinRT framework and had some success with that. I have also included the Universal App behaviours SDK in my project and tried the following (put together from Windows 8.1 examples but using the UWP SDK).

XAML

<Page
   xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
   xmlns:core="using:Microsoft.Xaml.Interactions.Core" />
...
<ComboBox ItemsSource="{Binding InputQuantities}">
   <interactivity:Interaction.Behaviors>
      <core:EventTriggerBehavior EventName="SelectionChanged">
         <core:InvokeCommandAction Command="{Binding SomeComboBoxCommand}" CommandParameter="Foo" />
      </core:EventTriggerBehavior>
   </interactivity:Interaction.Behaviors>
</ComboBox>

View Model

public RelayCommand SomeComboBoxCommand {get; set;}

However, the core:InvokeCommandAction isnt part of the Behaviours SDK and i get Invalid Type: expected type is 'Microsoft.Xaml.Interactivity.ActionCollection'. I've tried to use an ActionCollection.... but I'm not sure I know what I'm doing with that.

Ive successfully got it to work with compiled bindings and using Laurent's Blog Post:

XAML

<ComboBox ItemsSource="{Binding InputQuantities}" SelectionChanged="{x:Bind Vm.SomeComboBoxCommand }" />

View Model

public void SomeComboBoxCommand(object sender, SelectionChangedEventArgs e){//do stuff}

I know this isnt what Laurent is intending to demonstrate here and I think doing this is breaking the decoupling of the view and VM by then having to reference a UI component in my view model to get the selected item. But I've seen references to doing this during my research.

So how can I get this working using The Universal App interaction behaviours, if that's the right way to do it of course?

Update 1. This is what I attempted to add, believing, incorrectly that I was adding the universal app behaviours SDK. I didn't notice at the time that it was targeting Windows 8.1. Behaviours SDK

However, my questions still stands: Why wont the InvokeActioncommandwork and why is it throwing the mentioned error? I will look at the other posts as soon as I get to work.

Update 2 After testing this on my works PC (exact same code as above, 1st example and the same behaviours SDK) it works fine and I'm getting the behaviour that I would expect. I need to test again on my home PC to see what has gone wrong. (Thanks to Justin XL for sticking with me)

Update 3 For completeness, after returning home I got the latest version of my project (from being checked in on my works PC) and it now also works on my home PC. I'm not sure what state my Visual Studio was in but it had sufficiently confused me enough to post this question. At least this should serve as a document on how to do what is described in the title. Thanks for all your help.

like image 772
Neil Watson Avatar asked Aug 31 '15 18:08

Neil Watson


1 Answers

We seem to be getting this question a lot lately, in several different variants...

I'm not familiar with Universal App but is there any specific reason you're trying to use an event? WPF/Silverlight etc are designed to be data driven, all you need to do is bind the ComboBox's SelectedItem member to a property in your view model and the setter will get called whenever the user selects a new item. Often times you have to do exactly the same processing in response to other parts of your view model changing it (e.g. in Master-Child views) so having that logic in a single place generally makes for a much cleaner architecture.

like image 69
Mark Feldman Avatar answered Oct 24 '22 22:10

Mark Feldman