I rewrite my old UWP application using the паттерна MVVM , the following problems have arisen:


1. Navigation.

In the previous version I just wrote to navigate between pages:

 <Button Name="btSettings" Click="btSettings_Click"/> 

and in CodeBehind:

 private void btSettings_Click(object sender, RoutedEventArgs e) { Frame.Navigate(typeof(SettingsPage)); } 

How to do it now? In the VM I will add the OpenSettings command, for example, and make a binding:

 <AppBarButton Icon="Setting" Label="Настройки" Command="{Binding OpenSettings}"/> 

and what to write in the command method? Frame in VM is naturally unavailable


2. Binding the team to the event.

It is necessary to execute the command after the page loading, how to do it?

In a WPF application, I did something like this:

 xmlns:intr="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" <intr:Interaction.Triggers> <intr:EventTrigger EventName="Loaded"> <intr:InvokeCommandAction Command="{Binding LoadData}"/> </intr:EventTrigger> </intr:Interaction.Triggers> 

here, as I understand it, this assembly is not available

  • 2) Does the same thing in UWP not work? - VladD
  • @VladD, unfortunately, this assembly is not available in UWP - Andrey NOP
  • By the way, binding to the Load event is not necessary for things that are not related to the UI, you can get / load data from the model in the VM constructor, only this is how to do it asynchronously ... - Andrey NOP

4 answers 4

You can say quite recently (about a year ago I think) for UWP they introduced an additional feature: x:Bind in addition to the usual Binding . And now, without unnecessary gestures, you can bind a method from ViewModel to any event.

For example, in the ViewModel there is an isFriendSelected property to determine if the DeleteFriend method is DeleteFriend , then on the Click event on the button, you can call the DeleteFriend method from the ViewModel like this:

 <Button Click="{x:Bind ViewModel.DeleteFriend}" IsEnabled="{x:Bind ViewModel.IsFriendSelected}" /> 

    On the second part of the question: Interactions are available in UWP, under a different name. You need the nuget-package Microsoft.Xaml.Behaviors.Uwp.Managed .

    Well, they are a little different there. Event'ov no, but there are Behavior'y. So your code should look like this:

     <Page x:Class="..." xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:..." xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:core="using:Microsoft.Xaml.Interactions.Core" ...> <i:Interaction.Behaviors> <core:EventTriggerBehavior EventName="Loaded"> <core:EventTriggerBehavior.Actions> <core:InvokeCommandAction Command="{Binding LoadData}"/> </core:EventTriggerBehavior.Actions> </core:EventTriggerBehavior> </i:Interaction.Behaviors> 
    • one
      In UWP, it is now quite easy to attach methods from the ViewModel via x:Bind - Bulson
    1. Wrote your own NavigationService :

       sealed class NavigationService { public void Navigate(Type sourcePage) { var frame = (Frame)Window.Current.Content; frame.Navigate(sourcePage); } public void Navigate(Type sourcePage, object parameter) { var frame = (Frame)Window.Current.Content; frame.Navigate(sourcePage, parameter); } public void GoBack() { var frame = (Frame)Window.Current.Content; frame.GoBack(); } private NavigationService() { } private static readonly Lazy<NavigationService> instance = new Lazy<NavigationService>(() => new NavigationService()); public static NavigationService Instance => instance.Value; } 

    Now the navigation looks something like @MakeMakeluv, but without using a third-party FW:

     public ICommand NavigateToSettingsPage => new DelegateCommand(o => NavigationService.Instance.Navigate(typeof(SettingsPage))); 

    I hope this does not go against the паттерна MVVM waiting for comments from experts.

    • In my opinion, quite nice. I, however, am not an expert on UWP. - VladD

    On the first question - if the application contains at least page 3 it makes sense not to reinvent the wheel, but use a framework, for example, Prism. The frameworks are just made for the convenience of routine operations such as navigation, state storage, etc. Navigation in a prism looks like this:

     public DelegateCommand NavigateToTargetPageCommand => new DelegateCommand(() => _navigationService.Navigate("Target", null)); 
    • Wow! And what is a _navigationService ? - VladD
    • Thanks for the offer, but before using the ready framework, you need to do it all yourself with the handles at least a couple of times. I think so. - Andrei NOP
    • @VladD is an INavigationService type service built into Prism that encapsulates all the navigation logic that is injected into the VM through the constructor. - Make Makeluv