1

I'm using the SimpleMVVM Toolkit.

I have a view (manage_view) with multiple buttons that will navigate (set a frame's source) to new views (manage_import_view, manage_scanners_view, etc). Each view has it's own VM.

For each of the views I set the datacontext to the VM by using a locator. The locator injects a ServiceAgent into the VM.

The problem is that when I navigate to the other views, the state of the previous view is lost. For instance I'd do an import on the Manage_Import_View and bind to properties on the VM. When I navigate to Manage_Scanners_View and then back to the Manage_Import_View, the properties that I bound to is lost.

I understand what is happening but Im not sure how to resolve it. How do I keep the state of the views when switching between them?

Looking forward to your thoughts on this.

(I've searched Switching between views according to state but it's not exactly what I need.)

Edit

My locator

public ImportViewModel ImportViewModel   
{  
    get  
    {  
        IIntegrationServiceAgent sa = new IntegrationServiceAgent();  
        return new ImportViewModel(sa);  
    }  
}  

In my view's XAML I set the datacontext

DataContext="{Binding Source={StaticResource Locator}, Path=ImportViewModel}"    

Navigation is like so

private void Navigate(string pageName)  
{  
    Uri pageUri = new Uri("/Views/" + pageName + ".xaml", UriKind.Relative);  
    this.SelectedPage = pageUri;  
    this.SelectedPageName = pageName;  
}  

I have a completion callback once import is complete. This sets the props that my view binds to - these are the ones that are reset after switching views.

    private void ImportCompleted(IntegrationResult intresult, Exception error)
    {
        if (error == null)
        {
            _errorCount = intresult.Errors.Count;
            ErrorList = intresult.Errors;

            ResultMessage = intresult.Message;
            ErrorMessage = (errorList.Count == 1 ? "1 error" : errorList.Count.ToString() + " errors");
            Notify(ImportCompleteNotice, null);  // Tell the view we're done                
            ShowErrorDialog(importType);
        }
        else
            NotifyError(error.Message, error);

        IsImportBusy = false;
    }
Community
  • 1
  • 1
ceebreenk
  • 1,031
  • 2
  • 14
  • 29

2 Answers2

0

This seems clunky to me. I am not entirely sure why this is happening but I can guess... You are loading the SelectedPage from Uris each time they are requested, this will set and parse the XAML each time they are loaded which will effect your bindings. Here's what I would do:

First on the application start-up, load all of the Views into a view list

private Dictionary<string, Uri> viewUriDict;
private List<string> viewNameList = new List<string>() 
{
    "ViewA",
    "ViewB"
};

// The main View Model constructor.
public MainViewModel()
{
    viewUriDict = new Dictionary<string, Uri>();
    foreach (string s in viewNameList)
        viewUriDict.Add(s, new Uri("/Views/" + s + ".xaml", UriKind.Relative);
    this.SelectedPageName = viewNameList[0];
}

private string selectedPageName;
public string SelectedPageName
{
    get { return this.selectedPageName; }
    set
    {
        if (this.selectedPageName == value)
            return;
        this.selectedPageName = value;
        this.SelectedPage = this.viewUriDict[this.selectedPageName];
        OnPropertyChanged("SelectedPageName"); // For INotifyPropertyChanged.
    }
}

private Uri selectedPage;
private Uri selectedPageName
{
    get { return this.selectedPage; }
    set
    {
        if (this.selectedPage == value)
            return;
        this.selectedPage = value;
        OnPropertyChanged("SelectedPage"); // For INotifyPropertyChanged.
    }
}

So now the Uri list is cached in your main window/app. Navigation would then become

private void Navigate(string pageName)  
{  
    this.SelectedPageName = pageName;
}  

or by merely setting this.SelectedPageName = "PageX".

The second thing I would do is lazily instantiate the InportViewModel service agent. I am not sure how this is called, but I would not re-create the service agent on every call...

private IIntegrationServiceAgent sa;
public ImportViewModel ImportViewModel   
{  
    get  
    {  
        if (sa == null)
            sa = new IntegrationServiceAgent();  
        return new ImportViewModel(sa);  
    }  
} 

This may resolve your issue, or might not. Either way I hope it is of some value. If I were you, I would look at using Prism to do this type of thing, although it might be overkill if this is a small project.

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277
  • Hey man, thanks for the detailed answer. I see what you're getting at and it makes sense however the problem persist. I'm implementing your suggestions either way as it feels right to manage my views like that. I'll keep scratching and see what I come up with. Cheers – ceebreenk Feb 06 '14 at 11:47
0

For anyone who've experience the same puzzle, I've found the answer here and here . tonysneed's reply on the second link explains it.

ceebreenk
  • 1,031
  • 2
  • 14
  • 29