Reputation: 725
I am trying to pass a value to a view model from another view model before navigating to the page attached to that view model. I was previously passing it to the view, then passing it to the view model. This seems like a clumsy way of doing things. I am not using any kind of framework so that is not an option. At the moment the property is set as static and this works but im not sure if this is good practice. The code:
View model 1:
This command opens the new page:
public void OpenRouteDetails()
{
RouteStopPopOverViewModel.RouteName = "TestRoute";
App.Page.Navigation.PushAsync(new RouteStopPopOverView());
}
View model 2: (RouteStopPopOverViewModel)
public static string RouteName { get; set; }
This does work but I would prefer not to use static as a way to achieve this. Is there some way to set the RouteName property without using static or passing it through view-> view model. I have seen some answers about this but they don't seem to answer to question clearly.
Upvotes: 3
Views: 4565
Reputation: 6953
As you are using the MVVM pattern, you can use one of the many MVVM Frameworks to achieve this.
I use FreshMvvm and it allow me to pass parameters between view models like this
await CoreMethods.PushPageModel<SecondPageModel>(myParameter, false);
Then in SecondPageModel I can see access the parameters in the Init method
private MyParamType _myParameter;
public override void Init(object initData)
{
base.Init(initData);
var param = initData as MyParamType;
if (param != null)
{
_myParameter = param;
}
}
You can find more details about FreshMvvm here although most MVVM frameworks have similar functionality.
Upvotes: 0
Reputation: 1638
Share a controller class between view models.
The same instance has to be supplied to the constructor in both view models.
So you can set values, and listen for events in both view models.
The controller class becomes the intermediary.
public class SharedController : IControlSomething
{
private string _sharedValue;
public string SharedValue
{
get => _sharedValue;
set
{
if (_sharedValue == value)
return;
_sharedValue = value;
OnSharedValueUpdated();
}
}
public event EventHandler SharedValueUpdated;
protected virtual void OnSharedValueUpdated()
{
SharedValueUpdated?.Invoke(this, EventArgs.Empty);
}
}
public class ViewModel1
{
private readonly IControlSomething _controller;
public ViewModel1(IControlSomething controller)
{
// Save to access controller values in commands
_controller = controller;
_controller.SharedValueUpdated += (sender, args) =>
{
// Handle value update event
};
}
}
public class ViewModel2
{
private readonly IControlSomething _controller;
public ViewModel2(IControlSomething controller)
{
// Save to access controller values in commands
_controller = controller;
_controller.SharedValueUpdated += (sender, args) =>
{
// Handle value update event
};
}
}
Upvotes: 2
Reputation: 6707
If there is a hierarchy you could express that in a parent to both of them.
public class Route
{
private string Name;
}
public class RouteSelectedArgs : EventArgs
{
public Route Selected { get; set; }
}
public interface IRouteSelection
{
event EventHandler<RouteSelectedArgs> RouteSelected;
}
public interface IRouteDetails { }
public class RouteWizard
{
public UserControl view { get; set; }
private IRouteSelection _selection;
private IRouteDetails _details;
public RouteWizard(IRouteSelection selection, IRouteDetails details)
{
_selection = selection;
_details = details;
_selection.RouteSelected += Selection_RouteSelected;
view = MakeView(_selection);
}
private void Selection_RouteSelected(object sender, RouteSelectedArgs e)
{
_selection.RouteSelected -= Selection_RouteSelected;
view = MakeView(_details, e.Selected);
}
private UserControl MakeView(params object[] args)
{
////magic
throw new NotImplementedException();
}
}
Upvotes: 0
Reputation: 889
here the sample you can achieve your requirement easily with navigation
public class ViewModelFrom : BaseViewModel
{
async Task ExecuteCommand()
{
string routeName="value to trasfer";
Navigation.PushAsync(new View(routeName));
}
}
public partial class View : ContentPage
{
public View(string routeName)
{
InitializeComponent();
BindingContext = new ViewModelTo(routeName);
}
}
public class ViewModelTo : BaseViewModel
{
public string RouteName { get; set; }
public ViewModelTo(string routeName)
{
RouteName=routeName;
}
}
Upvotes: 1