Custom cell is not updating viewmodel when user enters input into cell - xamarin

I am new into MVVMCross(Xamarin.iOS). So, I could be in wrong direction. If somebody can point me in right direction or point out what I am doing wrong.
I have already taken a look over "CustomerManagement" and "Collection" sample of MVVMCross.
Basically I am trying to create Settings screen.
I have one custom UITableViewCell with one text field. See my code below. "EntryTF" is IBOutleted. "EntryTF" is binded with "FirstName" property of Model. Setting value to "FirstName" is reflecting on UI. But if user enter something to textfield doesn't save to model. In short cell is not updating viewmodel/model.
Please note that I want to keep binding out of cell class. So, I can reuse this cell for other models or fields.
public partial class PlainEntryCell : UITableViewCell
{
public static readonly UINib Nib = UINib.FromName ("PlainEntryCell", NSBundle.MainBundle);
public static readonly NSString Key = new NSString ("PlainEntryCell");
public PlainEntryCell (IntPtr handle) : base (handle)
{
// this.DelayBind (() => {
// this.AddBindings(new Dictionary<object,string> ())
// });
}
public static PlainEntryCell Create ()
{
return (PlainEntryCell)Nib.Instantiate (null, null) [0];
}
public string CaptionText {
get {
return EntryTF.Text;
}
set {
EntryTF.Text = value;
}
}
}
My View Model:
public class RegisterViewModel: MvxViewModel
{
private RegisterModel _registerModel;
public RegisterViewModel ()
{
_registerModel = new RegisterModel ();
_registerModel.FirstName = "Test";
}
public RegisterModel Customer {
get { return _registerModel; }
set {
_registerModel = value;
RaisePropertyChanged ("Customer");
}
}
}
Model:
public class RegisterModel:MvxNotifyPropertyChanged
{
private string _firstName;
public string FirstName {
get { return _firstName; }
set {
_firstName = value;
RaisePropertyChanged ("FirstName");
}
}
public string LastName { get; set; }
public string PhoneNum { get; set; }
public string Email { get; set; }
public string Pin { get; set; }
}
TableView Source:
public class RegisterTableViewSource: MvxTableViewSource
{
RegisterView _registerView;
public RegisterTableViewSource (UITableView tableView, RegisterView registerView)
: base (tableView)
{
_registerView = registerView;
tableView.RegisterNibForCellReuse (PlainEntryCell.Nib,
PlainEntryCell.Key);
//tableView.RegisterNibForCellReuse (UINib.FromName ("DogCell", NSBundle.MainBundle), DogCellIdentifier);
}
protected override UITableViewCell GetOrCreateCellFor (UITableView tableView, Foundation.NSIndexPath indexPath, object item)
{
var cell = TableView.DequeueReusableCell (PlainEntryCell.Key, indexPath);
cell.Bind (_registerView, "CaptionText Customer.FirstName");
return cell;
//return (UITableViewCell)TableView.DequeueReusableCell (PlainEntryCell.Key, indexPath);
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return 2;
}
}
Update:
Still not able to get the answer.
In above code I want to bind "EntryTF" with property of model. But I want to keep binding outside class. So, CaptionText property is not necessary if someone can point out direct way of binding to "EntryTF"
Is not there a way of creating BindableProperty just like Xamarin Forms? I feel MVVMCross is matured framework so, why there is not a solution of this kind of simple things.
I would also love to here if there is any simple/other way of achieving the same things.
I have also looked MTD but didn't find much useful for custom cell and it is also need good amount of my learning.

Basically I am trying to create Settings screen.
Take a look at using monotouch dialog, mt.d, with MvvmCross, Use Mvvmcross Binding with MonoTouch.Dialog (Lists and Commands)
That StackOverflow question/answer will get you started using mt.d with mvvmcross. I use it for basic settings screens in my applications.
Cell Isn't Updating
I wrote an article on using custom cells with MvvmCross, see
http://benjaminhysell.com/archive/2014/04/mvvmcross-custom-mvxtableviewcell-without-a-nib-file/
I have found it easier not to use nib files and fully describe my UI in code.
It looks like in your public partial class PlainEntryCell : UITableViewCell you don't ever bind the cell to the ViewModel. You have that commented out. I would try something like, while adding http://slodge.blogspot.com/2013/07/playing-with-constraints.html to your application for layout:
public PlainEntryCell()
{
CreateLayout();
InitializeBindings();
}
UILabel captionText;
private void CreateLayout()
{
SelectionStyle = UITableViewCellSelectionStyle.None;
Accessory = UITableViewCellAccessory.DisclosureIndicator;
captionText = new UILabel();
ContentView.AddSubviews(captionText);
ContentView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
const int vPadding = 10;
const int hPadding = 20;
ContentView.AddConstraints(
captionText.AtTopOf(ContentView).Plus(vPadding),
captionText.AtLeftOf(ContentView).Plus(hPadding),
captionText.Width().EqualTo(UIScreen.MainScreen.Bounds.Width / 2)
);
private void InitializeBindings()
{
this.DelayBind(() =>
{
var set = this.CreateBindingSet<PlainEntryCell, RegisterViewModel();
set.Bind(captionText).To(vm => vm.CaptionText);
set.Apply();
});
}
}

Your custom cell needs to implement INotifyPropertyChanged to allow the ViewModel to be notified of a value change in your cell properties.
public partial class PlainEntryCell : UITableViewCell, INotifyPropertyChanged
{
public static readonly UINib Nib = UINib.FromName ("PlainEntryCell", NSBundle.MainBundle);
public static readonly NSString Key = new NSString ("PlainEntryCell");
public PlainEntryCell (IntPtr handle) : base (handle)
{
// this.DelayBind (() => {
// this.AddBindings(new Dictionary<object,string> ())
// });
}
public static PlainEntryCell Create ()
{
return (PlainEntryCell)Nib.Instantiate (null, null) [0];
}
public string CaptionText {
get {
return EntryTF.Text;
}
set {
EntryTF.Text = value;
RaisePropertyChanged("CaptionText");
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}

Related

DataBinding issue in Xamarin Forms

I have a new Xamarin Forms 5 app and I'm having trouble with data binding.
First, I display a message that tells the user how many items are in his list. Initially, this is 0. It's displayed by DisplayMessage property of the view model.
Then, the Init() method gets called and once the API call is finished, there are some items in MyList. I put break points to make sure that the API call works and I end up with some data in MyList property.
Because I change the value of message in my Init() method, I was expecting the message to change and display the number of items in the list but it's not changing even though I have some items in MyList.
I created a new ViewModel that looks like this:
public class MyViewModel : BaseViewModel
{
public List<MyItem> MyList { get; set; } = new List<MyItem>();
string message = "You have no items in your list... ";
public string DisplayMessage
{
get => message;
set
{
if(message == value)
return;
message = value;
OnPropertyChanged();
}
}
public async void Init()
{
var data = await _myService.GetData();
if(data.Count > 0)
message = $"You have {data.Count} items in your list!";
MyList = data;
}
}
My MainPage code behind looks like this:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
MyViewModel _vm;
MainPage()
{
InitializeComponent();
_vm = new MyViewModel();
this.BindingContext = _vm;
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.Init();
}
}
I didn't change anyting in the base view model, except I added my service and it looks like this:
public class BaseViewModel : INotifyPropertyChanged
{
public IMyApiService MyApi => DependencyService.Get<IMyApiService>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
I'd appreciatae someone telling me where my mistake is. Thanks.
Without seeing the Xaml, I can't 100% answer, but here are a couple of things I see:
You are setting the "message" through the field, not the property. Since you are setting the field directly the OnPropertyChanged event isn't firing so the UI isn't getting notified that the value has changed.
I am guessing you are binding "MyList" to some sort of CollectionView or something? If it's a readonly view, using a List is ok as the collection is never updated. However, if you plan on adding or removing items at runtime, it needs to be an "ObservableCollection" for the same reason as above, the UI isn't notified of new items in a List, but an ObservableCollection will notify the UI of changes to it, so it can update.
Is what Jason mentions above in his comment. The MyList property should be setup like the other properties with the OnPropertyChanged.

Implementing a UISearchController using MVVMCross

I have an app which I am converting from iOS only to iOS & Droid using MVVMCross.
In my current app I have a map view that uses a UISearchController that allows the user to search for locations nearby. This is based on the Xamarin example and works fine:
Xamarin Map Example
For the conversion I have:
a MapView bound to a MapViewModel.
A search service which is injected into MapViewModel.
Created a UISearchController and bound the search text to a property on the MapViewModel.
When the text is updated the search is called and the results are retrieved. What I am struggling with is how to bind the results back to a SearchResultsView as this is presented by the UISearchController.
Can anyone give me advice or point me in the right direction to solve this.
I have the code snippet below to give an idea of what I have relied so far.
[MvxFromStoryboard]
public partial class MapView : MvxViewController<MapViewModel>
{
public MapView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var searchResultsController = new SearchResultsView();
//Not sure if this is required
//var searchUpdater.UpdateSearchResults += searchResultsController.Search;
var searchController = new UISearchController(searchResultsController)
{
//Nore sure if this is required
//SearchResultsUpdater = searchUpdater
};
searchController.SearchBar.SizeToFit();
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
searchController.SearchBar.Placeholder = "Enter a search query";
searchController.HidesNavigationBarDuringPresentation = false;
DefinesPresentationContext = true;
NavigationItem.TitleView = searchController.SearchBar;
//Bind to View Model
var set = this.CreateBindingSet<MapView, MapViewModel>();
set.Bind(searchController.SearchBar).To(vm => vm.SearchQuery);
set.Apply();
}
}
public class SearchResultsUpdator : UISearchResultsUpdating
{
public event Action<string> UpdateSearchResults = delegate { };
public override void UpdateSearchResultsForSearchController(UISearchController searchController)
{
this.UpdateSearchResults(searchController.SearchBar.Text);
}
}
[MvxFromStoryboard]
public partial class SearchResultsView : MvxTableViewController<SearchResultsViewModel>
{
public SearchResultsView() { }
public SearchResultsView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var source = new SearchResultsTableViewSource(TableView);
TableView.Source = source;
var set = this.CreateBindingSet<SearchResultsView, SearchResultsViewModel>();
set.Bind(source).To(vm => vm.Results);
set.Apply();
}
}
[MvxFromStoryboard]
public partial class SearchResultsView : MvxTableViewController<SearchResultsViewModel>
{
public SearchResultsView() { }
public SearchResultsView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var source = new SearchResultsTableViewSource(TableView);
TableView.Source = source;
var set = this.CreateBindingSet<SearchResultsView, SearchResultsViewModel>();
set.Bind(source).To(vm => vm.Results);
set.Apply();
}
}
I have posted this in case someone else is looking for an example. I decided the best way to do this was to let iOS handle the search view controller for the results. Code follows. Feel free to correct or suggest a better alternative
View
[MvxFromStoryboard]
public partial class MapView : MvxViewController
{
UISearchController _searchController;
SearchResultsViewController _searchResultsController;
private IDisposable _searchResultsUpdateSubscription;
private IMvxInteraction _searchResultsUpdatedInteraction;
public IMvxInteraction SearchResultsUpdatedInteraction
{
get => _searchResultsUpdatedInteraction;
set
{
if (_searchResultsUpdateSubscription != null)
{
_searchResultsUpdateSubscription.Dispose();
_searchResultsUpdateSubscription = null;
}
_searchResultsUpdatedInteraction = value;
if (_searchResultsUpdatedInteraction != null)
{
_searchResultsUpdateSubscription = _searchResultsUpdatedInteraction.WeakSubscribe(OnSearchResultsUpdated);
}
}
}
private void OnSearchResultsUpdated(object sender, EventArgs e)
{
_searchResultsController.SearchResults = Results;
_searchResultsController.ReloadSearchTable();
}
public List<Placemark> Results { get; set; }
public MapView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
//Bind to View Model
var set = this.CreateBindingSet<MapView, MapViewModel>();
set.Bind(_searchController.SearchBar).To(vm => vm.SearchQuery);
set.Bind(this).For(v => v.Results).To(vm => vm.Results);
set.Bind(this).For(v => v.SearchResultsUpdatedInteraction).To(vm => vm.SearchResultsUpdatedInteraction).OneWay();
set.Apply();
}
ViewModel
public class MapViewModel : MvxViewModel
{
readonly ILocationService _locationService;
private MvxInteraction _searchResultsUpdatedInteraction = new MvxInteraction();
public IMvxInteraction SearchResultsUpdatedInteraction => _searchResultsUpdatedInteraction;
public MapViewModel(ILocationService locationService)
{
_locationService = locationService;
}
//***** Properties *****
private List<Placemark> _results;
public List<Placemark> Results
{
get => _results;
set
{
_results = value;
RaisePropertyChanged();
}
}
private string _searchQuery;
public string SearchQuery
{
get => _searchQuery;
set
{
_searchQuery = value;
//Task.Run(UpdateResultsAsync).Wait();
RaisePropertyChanged();
UpdateResultsAsync();
}
}
//***** Privates *****
private async Task UpdateResultsAsync()
{
Results = await _locationService.SearchForPlacesAsync(_searchQuery);
_searchResultsUpdatedInteraction.Raise();
}
}
SearchResultsViewController
public class SearchResultsViewController : UITableViewController
{
static readonly string mapItemCellId = "mapItemCellId";
public List<Placemark> SearchResults { get; set; }
public SearchResultsViewController()
{
SearchResults = new List<Placemark>();
}
public override nint RowsInSection(UITableView tableView, nint section)
{
return SearchResults == null ? 0 : SearchResults.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(mapItemCellId);
if (cell == null)
cell = new UITableViewCell();
cell.TextLabel.Text = SearchResults[indexPath.Row].FeatureName;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
//Do stuff here
}
public void ReloadSearchTable()
{
this.TableView.ReloadData();
}
}

Scrolling to start of Xamarin Forms ListView with header

I'm having some trouble scrolling to the top of a ListView in Xamarin Forms. I can scroll to the first item by calling ScrollTo and passing the first item. The problem is that when the list has a header item, I can't find a way to scroll to the header. Is this possible? The only work around I can think of is to not use the header and just have another item at the start of the ItemSource list that acts as a header but I'd rather use the header if possible. Thanks.
So I've solved this myself now. My solution was to subclass ListView and add a public ScrollToTop method which invokes an internal ScrollToTopRequestedEvent when called. I then subclassed the ListViewRenderer on each platform and registered for the event.
In the Android renderer I'm then calling Control.SmoothScrollToPositionFromTop(0, 0) to scroll to top.
In the iOS rendered I'm calling Control.ScrollRectToVisible(new CoreGraphics.CGRect(0, 0, 1, 1), true).
Wah all credits #Gareth Wynn, man that was cool thx.
Anyway here's the code for everyone to use, change class names and namespace, iOS not included, do same as for Android just using Gareth Wynn's hint in parallel answer:
SHARED NiftyListView.cs :
using System;
using Xamarin.Forms;
namespace AppoMobi
{
public class NiftyListView : CListView
{
public event EventHandler EventScrollToTop;
//-------------------------------------------------------------------
public void ScrollToTop(bool animate=true)
//-------------------------------------------------------------------
{
//bool animate is not used at this stage, it's always animated.
EventScrollToTop?.Invoke(this, EventArgs.Empty);
}
}
}
ANDROID NiftyListView.Android.cs :
using System;
using AppoMobi;
using AppoMobi.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using ListView = Xamarin.Forms.ListView;
[assembly: ExportRenderer(typeof(NiftyListView), typeof(NiftyListViewRenderer))]
namespace AppoMobi.Droid.Renderers
{
//-------------------------------------------------------------------
class NiftyListViewRenderer : ListViewRenderer
//-------------------------------------------------------------------
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
var view = (NiftyListView)Element;
if (view == null) return;
view.EventScrollToTop += OnScrollToTop;
}
//-------------------------------------------------------------------------------------------
public async void OnScrollToTop(object sender, EventArgs eventArgs)
//-------------------------------------------------------------------------------------------
{
Control.SmoothScrollToPositionFromTop(0, 0);
}
}
}
ScrollTo(Object, Object, ScrollToPosition, Boolean)
Scrolls the ListView to the item in the group
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.listview.scrollto?view=xamarin-forms
Model for each group:
public class Notification {
public int Id { get; set; }
public string Title { get; set; };
public Notification(int id, string title) {
Id = id;
Title = title;
}
}
Group-Model for ItemSource:
public class NotificationGroup: List<Notification> {
public string Title { get; set; }
public string ShortTitle { get; set; }
public NotificationGroup(string title) {
Title = title;
}
}
Sample Data & Usage:
//SAMPLE DATA
var notifications = new ObservableCollection <NotificationGroup> {
new NotificationGroup("Group-01") {
new Notification(1, "Item-1"),
new Notification(2, "Item-2")
},
new NotificationGroup("Group-02") {
new Notification(3, "Item-3"),
new Notification(4, "Item-4")
}
};
YourListViewName.ItemSource = notifications;
//USING
YourListViewName.ScrollTo(notifications.First()[0], notifications.First(), ScrollToPosition.Start, true);

Windows Phone Page navigation in MVVM

I am using MVVM in one of the app. I have created different project for Model, View and View Model.
I need to navigate to another XAML from ViewModel. I found some solution using MVVM light. Is there any way of implementing navigation from view model without using MVVM light.
Simple as that,
IF you want to navigate from page1 to page2,
private void MoveToPage2FromPage1()
{
NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
}
How to perform page navigation on Windows Phone 8
You can store current page url on a notify property of Shared ViewModel in App. After that, it is easy to catch the change of this url and navigate to the correct url by observing it.
public class AppViewModel : INotifyPropertyChanged
{
public string CurrentPageURL { get; set; }
private string _currentPageURL;
public string CurrentPageURL
{
get { return _currentPageURL;}
set
{
if (_currentPageURL==value)
return; // to prevent reload the same page.
_currentPageURL = value;
NotifyPropertyChangedCurrentPageURL
}
}
// INotifyPropertyChanged implementations
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
// Store in static singleton instance of AppViewModel
public class App : Application
{
private static Lazy<AppViewModel> _ViewModel=new Lazy<ViewModel>();
public static AppViewModel ViewModel { get { return _ViewModel.Value; } }
....
public App()
{
AppViewModel.PropertyChanged=(s,a) =>
{
if (a.PropertyName=="CurrentPageURL")
{
NavigationService.Navigate(new Uri(AppViewModel.CurrentPageURL, UriKind.Relative));
};
}
}
}
// Usage sample
public class Page1ViewModel
{
private btnMoveNextPage_Click(object s, EventHandler a) {
App.ViewModel.CurrentURL="~/Page2.xaml";
}
}

NavigationService throws NullReferenceException

Using MVVM Light, I'm trying to develop a rather simple WP7 application. I've run into a problem using the navigation service. I can navigate to a page, but after pressing the back button I can't navigate to the same page again. NavigationService throws a NullReferenceException.
I have implemented my navigation using Messaging from the GalaSoft.MvvmLight.Messaging namespace. All my views inherits from a customized PhoneApplicationPage base class that registrers a listener on "NavigationRequest":
public class PhoneApplicationPage : Microsoft.Phone.Controls.PhoneApplicationPage
{
public PhoneApplicationPage() : base()
{
Messenger.Default.Register<Uri>(this, "NavigationRequest", (uri) => NavigationService.Navigate(uri));
}
}
From my view models I post Uri's to this listener:
SendNavigationRequestMessage(new Uri("/View/AppSettingsView.xaml", UriKind.Relative));
Like i said, this works except when navigating after pressing the Back button.
Why is this and how can I solve it?
Is there a better way to implement navigation using MVVM Light?
I'm using MVVM Light as well. I have a class called PageConductor, which is based on what John Papa (Silverlight MVP) from Microsoft uses. Here's the PageConductor Service I use
public class PageConductor : IPageConductor
{
protected Frame RootFrame { get; set; }
public PageConductor()
{
Messenger.Default.Register<Messages.FrameMessage>(this, OnReceiveFrameMessage);
}
public void DisplayError(string origin, Exception e, string details)
{
string description = string.Format("Error occured in {0}. {1} {2}", origin, details, e.Message);
var error = new Model.Error() { Description = description, Title = "Error Occurred" };
Messenger.Default.Send(new Messages.ErrorMessage() { Error = error });
}
public void DisplayError(string origin, Exception e)
{
DisplayError(origin, e, string.Empty);
}
private void OnReceiveFrameMessage(Messages.FrameMessage msg)
{
RootFrame = msg.RootFrame;
}
private void Go(string path, string sender)
{
RootFrame.Navigate(new Uri(path, UriKind.Relative));
}
public void GoBack()
{
RootFrame.GoBack();
}
}
In my MainPage.xaml.cs constructor, I have this, which creates an instance of my ContentFrame in my PageConductor service.:
Messenger.Default.Send(new Messages.FrameMessage() { RootFrame = ContentFrame });
I then use dependency injection to instantiate an instance of my PageConductor Service into my MainPage ViewModel. Here is my MainViewModel class:
protected Services.IPageConductor PageConductor { get; set; }
public RelayCommand<string> NavigateCommand { get; set; }
public MainViewModel(Services.IPageConductor pageConductor)
{
PageConductor = pageConductor;
RegisterCommands();
}
private void RegisterCommands()
{
NavigateCommand = new RelayCommand<string>(
(source) => OnNavigate(source));
}
private void OnNavigate(string sender)
{
PageConductor.GoToView(sender, "main");
}
Notice the instance of my PageConductorService as a parameter in my MainViewModel constructor method. I pass this in via my ViewModelLocator:
private readonly TSMVVM.Services.ServiceProviderBase _sp;
public ViewModelLocator()
{
_sp = Services.ServiceProviderBase.Instance;
CreateMain(_sp);
}
#region MainPageViewModel
public static MainViewModel MainStatic
{
get
{
Services.ServiceProviderBase SP = Services.ServiceProviderBase.Instance;
if (_main == null)
{
CreateMain(SP);
}
return _main;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return MainStatic;
}
}
public static void ClearMain()
{
_main.Cleanup();
_main = null;
}
public static void CreateMain(Services.ServiceProviderBase SP)
{
if (_main == null)
{
_main = new MainViewModel(SP.PageConductor);
}
}
#endregion
For further reference, my Messages.FrameMessage class is simply:
internal class FrameMessage
{
public Frame RootFrame { get; set; }
}
I've had no issues with forward/back buttons.

Resources