简体   繁体   中英

MVVM-Light pass data to new ViewModel

Just fiddling around with some WP8.1 development + MVVM-Light toolkit and am having trouble trying to figure out how to achieve something..

Basically:

  • I have a View (let's call it View1 ) which has a control ( LongListSelector in this case) that is databound to a Collection of items (let's call them DataItem ) (which is populated by a Service from a ViewModel )

And I want it so:

  • When the user taps on a particular item in this control, it passes the item tapped (or a property of this item) to a new View (called View2 ), which will either create a new ViewModel for View2 or re-use an existing one (depending on the Key of the instances in SimpleIoC , determined by some property in the DataItem tapped).
  • This new ViewModel then uses the passed property of the DataItem tapped in its' constructor to fetch data from a different Service

So how can I achieve this? I am thinking of Creating/Registering the new ViewModel on the SelectionChanged event of the control, passing it in the Service and Property like so:

    private void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DataItem item = e.AddedItems[0] as DataItem;

        SimpleIoc.Default.Register(() => new ViewModel2(new Model2Service(), item.Name));

        NavigationService.Navigate(new Uri("/View2.xaml", UriKind.Relative));
    }

Which works fine for the first DataItem tapped, but not when a second is tapped. Note : I couldn't register ViewModel2 in ViewModelLocator as I couldn't get DataItem properties passed to the constructor for ViewModel2 , which is why I'm trying to Register it elsewhere.

Not sure if this is abiding by MVVM architecture, I suppose not as this answer states that I shouldn't be handling this in my View .

So to recap, I want a user to be able to tap on an item in a LongListSelector which will then navigate the user to a new View which is bound to a new (or existing) ViewModel according to a property of the selected item. How can I achieve this?

Any help would be greatly appreciated.

Have you tried using the Messenger in MVVMLight? Try creating the instance of the ViewModel2 in ViewModelLocator with the key being some default value. In the ViewModel's constructor, register to receive a string property (assuming item.Name is a string ) like this:

MessengerInstance.Register<string>(this,name=>{NameProperty=name;});

Then in the LongListSelector_SelectionChanged , send the item.Name like this:

Messenger.Default.Send<string>(item.Name);

And then navigate to the page.


Marked as solution but whole comment thread below reveals more details

If you are using UWP with Template Studio 10 and MVVM Light and want to either:

  • Access the parameter that is passed in the NavigationServicesEx.Navigate method

  • Call a method in your ViewModel when a page is navigated to.

This blog by Marco Minerva is the only guidance I could find that is up to up to date with UWP, Templates Studio 10 and MVVM Light 5.0 (thanks again Marco!)

tl;dr It works by hooking in to the Frame_Navigating event that it missing from the vanilla NavigationServiceEx class.

Create the INavigable interface described in the blog:

public interface INavigable
{
    Task OnNavigatedToAsync(object parameter, NavigationMode mode);
    void OnNavigatingFrom(NavigatingCancelEventArgs e);
    void OnNavigatedFrom();
}

Add a handler for the Frame.Navigating event in the NavigationServicesEx class (with some additional plumbing, see blog) then realise the INavigable interface in your ViewModels.

You will then be able to access the parameter that you passed in your Navigate call:

NavigationServiceEx.Navigate(typeof(DestinationPage).FullName, yourParameter);

In the OnNavigatedToAsync method that you implement in your ViewModel:

public Task OnNavigatedToAsync(object parameter, NavigationMode mode)
{
    if (parameter != null)
    {
        YourThing thing = parameter as YourThing;
        this.UseYourThing(thing);
    }
    return Task.CompletedTask;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM