Search code examples
c#wpfmvvmprism-5

Issues with INavigationAware in Prism 5


I'm fairly new to WPF and MVVM with Prism and I'm having an issue with Prism navigation. Each time I navigate to a particular view, I want to load a new view; however, if I enter some data or fully process some data, navigate away and come back, the existing data is always kept in the view.

I have read similar issues here on SO such as this and this. Both point to using INavigationAware or IRegionMemberLifetime. I have tried to implement both in my ViewModel; however, none seem to solve the issue for me.

If I use INavigationAware and set IsNavigationTarget to false, the view never loads. If I use IRegionMemberLifetime and set KeepAlive to false, it still retains my data.

I could post code; however, it's simple and looks like the same that's in the linked issues. Has anyone had similar issues with Prism navigation?

Any help is appreciated.

Edit - Adding sample code

In an effort to get rid of any red herrings with other code I've got, I created a new Prism app with the bare necessities. My issue with the view not displaying when navigating back has cleared up; however, the view is still retaining the entered values.

Here is some sample code:

Model:

public class SomeObject
{
    public string ObjectName { get; set; }

}

I created a basic view with just two TextBox controls, 1 bound and 1 not:

<StackPanel>
    <TextBlock Text="ModuleA" />
    <TextBox Text="{Binding DisplayedSomeObject.ObjectName, UpdateSourceTrigger=PropertyChanged}" />
    <TextBox />
</StackPanel>

ViewModel:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
[RegionMemberLifetime(KeepAlive=false)]
public class ModuleAViewModel : BindableBase, IConfirmNavigationRequest, INavigationAware
{
    private SomeObject displayedSomeObject = new SomeObject();
    public SomeObject DisplayedSomeObject
    {
        get { return displayedSomeObject; }
        set
        {
            displayedSomeObject = value;
        }
    }

    [ImportingConstructor]
    public ModuleAViewModel()
    {

    }

    void IConfirmNavigationRequest.ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
    {
        continuationCallback(true);
    }


    bool INavigationAware.IsNavigationTarget(NavigationContext navigationContext)
    {
        return false;
    }

    void INavigationAware.OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    void INavigationAware.OnNavigatedTo(NavigationContext navigationContext)
    {
        var newSomeObject = new SomeObject();
        this.DisplayedSomeObject = newSomeObject;
    }
}

When I run this, both the bound and un-bound controls retain their values when navigated back to.


Solution

  • Have you done some troubleshooting on Navigation? Set a breakpoint to when the page is navigated to and see how all the data is coming back in. I thought I had the same problem before and I was foolishly loading a object into my VM that was never getting destroyed.

    Because of this, it appeared the VM was being kept alive, but in reality it was not. It would load like normal every time, but it would be pulling from the object that wasn't reloading.

    So, set a breakpoint on the navigateTo and step through to see if the data is getting reloaded or not.

    EDIT: Looking at the code above, I believe you need to add IRegionMemberLifetime as well. I am currently using Prism 4.5, so I don't know if this has changed in 5, but I have to add that for it to actually destroy it.

    public class ModuleAViewModel : BindableBase, IConfirmNavigationRequest, INavigationAware, IRegionMemberLifetime
    {
     ...
            bool IRegionMemberLifetime.KeepAlive
        {
            get { return false; }
        }
    }