MVVM Passing data between two views / view models - c#

I have two Pages:
Page 1
Page 2
and two ViewModels with the same properties:
ViewModel1
Properties:
FirstName1
LastName1
ViewModel2
Properties:
FirstName2
LastName2
Now I want to pass data(properties) between ViewModel1 to ViewModel2, and retrive this data on the Page 2.
How do I achieve this?

You could take a look at MVVMLight's Messenger. Here's is a tutorial that could guide you on your way. Basically, the idea is to use a messenger that's independent from your Views/ViewModels to send messages from/to them. Your Views/ViewModels register and send specific messages that contain properties values you want to pass along.

Your page could be constructed like so:
public class Page2 {
public ViewModel1 VM1;
public Page2() {
VM1 = new ViewModel1(new ViewModel2());
}
}
Your ViewModel1 could look like so, with pass-through properties:
public class ViewModel1 : Person {
private ViewModel2 _vm2;
public ViewModel1(ViewModel2 vm2) {
_vm2 = vm2;
}
public override string FirstName {
get { return _vm2.FirstName; }
}
public override string LastName {
get { return _vm2.LastName; }
}
}
We assume your ViewModel2 has some business logic or something
public class ViewModel2 : Person {
//Etc
}
Both inherit from the same base class:
public abstract class Person {
public abstract string FirstName { get; }
public abstract string LastName { get; }
}

You can either go with a parent ViewModel that both viewmodels inherit from or an Event Aggregator. Here is a simple one using Reactive Extensions.

Related

Pass diffrent viewmodel with other viewmodel to show page

I have question. I use to use Send to pass the viewmodel to show other page as shown below:
public class UsersViewModel : IUsersViewModel
{
void ShowCars()
{
MessagingCenter.Send<IUsersViewModel>(this, "ShowCarsViewPage");
}
}
As you see above, i use this. Now i have situation that i need to pass diffrent viewmoodel inside UsersViewModel. I want to add ShowBuildings inside UsersViewModel. The problem is as it's diffrent viewmodel to be passed i cannot use this which leds me to use new keyword and pass all dependencies. How can i overcome that?
void ShowBuildings()
{
MessagingCenter.Send<IBuildingsViewModel>(new Buildings(new DataStorage()), "ShowBuildingsViewPage");
}
My first thought is to pass that view model i need to use into UsersViewModel's ctor but not sure if this is right way like to insert another view model into other view model?:
public class UsersViewModel : IUsersViewModel
{
private readonly IBuildingsViewModel _buildingviewmodel;
UsersViewMode(IBuildingsViewModel buildingviewmodel)
{
_buildingviewmodel = buildingviewmodel;
}
//So then:
void ShowBuildings()
{
MessagingCenter.Send<IBuildingsViewModel>(_buildingviewmodel, "ShowBuildingsViewPage");
}
}
Check xamarin publisher documentation. The third parameter is the payload data that is being sent.
MessagingCenter.Send<MainPage, string>(this, "Hi", "John");
Tip: Try to bundle multiple ViewModels with an interface and pass that. In this way you will not be tied to specific ViewModels interfaces.
interface IBuildingCollection : IEnumerable<Building>
{
}
class ViewModel1 : IBuildingsViewModel, IBuildingCollection
{
}
class ViewModel2 : IBuildingsViewModel, IBuildingCollection
{
}
class UsersViewModel : IUsersViewModel
{
void ShowBuildings(IBuildingCollection collection)
{
MessagingCenter.Send<IUsersViewModel, IBuildingCollection>(this, "ShowBuildingsViewPage", collection);
}
}
class ReceiverViewModel : IReceiverViewModel
{
public ReceiverViewModel()
{
MessagingCenter.Subscribe<IUsersViewModel, IBuildingCollection>(this, "ShowBuildingsViewPage", myDelegate);
}
public void myDelegate(IBuildingCollection buildings)
{
// Do something with buildings
}
}

Xamarin Forms MVVM with an actual model

I'm fairly new to Xamarin and stumbled across MVVM and really like it as an architectural pattern. However, I found that most HowTo's and tutorials out there only address the VVM (i.e. View-ViewModel) side of things, probably for simplicity sake!?
I would like to know how the communication between a ModelView and its associated models takes place using the INotifyPropertyChanged paradigm and other things.
If I understand correctly, I personally would put stuff like data handling, data storage (collections), db connections and stuff like that into a model. At least this is how I would've been doing it in the good old MVC days. Following questions arouse in my mind:
Where do I create the model(s) and how do I assign them to ViewModels?
How do I properly connect Model and ViewModel such that property updates are propagated and can be handled correctly?
Would you set the model as a member of the ViewModel?
In my current example, I would like to implement a SensorModel which provides several sensory data which layers above can subscribe to. I would like to send updates whenever new sensor data is available to the layers above; i.e. a ViewModel, for instance.
I'd basically had something like this in mind:
class Sensor
{
int _id { get; set; }
string _name { get; set; }
}
class SensorModel
{
private List<Sensor> _sensors { get; set; }
public void addSensor(Sensor s) ...
public void removeSensor(Sensor s) ...
}
Does anybody have links to actual/complete MVVM examples, including the connection between Model and ViewModel?
Any help appreciated.
Use Lastest stable Xamarin Forms
MODELS
In the Project, create a Models folder
To store data, i usually use SQLite or a temp store:
class DataStore
{
public static List<SensorModel> SensorStore { get; set; }
}
Create the SensorModel model
class SensorModel
{
internal int Id { get; set; }
internal string Sensor { get; set; }
}
VIEWMODELS
In the Project, create a ViewModels folder
Create a SensorVM viewmodel
class SensorVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public System.Windows.Input.ICommand StartCommand { get; set; }
public string SensorName { get; set; }
public SensorVM()
{
DataStore.SensorStore = new List<SensorModel>();
StartCommand = new Xamarin.Forms.Command(StartSubmit);
}
private void StartSubmit(object paramter)
{
var sensor = new SensorModel()
{
Id = 1,
Sensor = SensorName
};
AddSensor(sensor);
}
public void AddSensor(SensorModel sensor)
{
//do something
DataStore.SensorStore.Add(sensor);
}
}
VIEWS
In the Project, create a Views folder
Create a Sensor.xaml view
<ContentPage.Content>
<StackLayout Spacing="10" Orientation="Vertical">
<Entry Text="{Binding SensorName}" />
<Button Command="{Binding StartCommand}" Text="Start" />
</StackLayout>
</ContentPage.Content>
In the code behind:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Sensor : ContentPage
{
SensorVM vm;
public Sensor()
{
InitializeComponent();
BindingContext = vm = new SensorVM();
}
}
Hope that helps.
I would like to know how the communication between a ModelView and its
associated models takes place using the INotifyPropertyChanged
paradigm and other things.
I think the best way to create a communication in MVVM is Messaging Center.
https://learn.microsoft.com/pt-br/xamarin/xamarin-forms/app-fundamentals/messaging-center
It's not coupled from device (sensor) code to view models ...
Your messages, in this model, active events that could acess your viewmodels as well as other structures.
A sample of this
In your view use :
public void MessegingCenterInit()
{
#region Bluetooth
MessagingCenter.Subscribe<string, string>("App", "Status_name", (sender, arg) =>
{
App.PVM.Name = $"{arg}";//using INotifyPropertyChanged and view model
viewmodelMethod();//using only a viewmodel
});
#endregion
}
in your model use:
public string Name
{
get { return name; }
set
{
name = value;
App.PVM.Add_patient.AddCanExecuteChanged();//PVM is a viewmodel
//The view model need to have INotifyPropertyChanged as a interface
}
}
In specific code you have (into a generic method or event):
string new_name = John;
MessagingCenter.Send<string,string>("App","Status_name",new_name);
There are several ways to do it, its a simple one, you can try use objects as sender with less information.
Regards
Xamarin itself gives a really good example with their default Master-Detail Solution.
Just create a new Xamarin.Forms App and select the Master-Detail Layout.
It includes several Views, ViewModels (with the BaseVIewModel) and some MockUp Data Classes.
For a start just have a look around there :)
In almost all cases there is no communication between the Model and ViewModel, and very rarely there is communication between the Model and View. If you need to communicate between Model and ViewModel it is extremely likely that you are doing something wrong.
To explain, your model usually describes some entity, like that you have the class Cat:
public class Cat
{
public string Color {get; set;}
}
It is generally used in ViewModel either as the field or as a Collection like:
public class CatsViewModel
{
public List<Cat> Cats {get; set;}
}
The cat shouldn't be able to update by itself, if it is updated it is done either by bindings with the view or somewhere from ViewModel.
So you have some architectural problems in your app, I think.

MVVM pattern for WPF: Model vs ViewModel

I can't really wrap my head around the following problem:
All I have in the application is a textboxfor the user input, a button for performing a background calculation on that input and a textblock. Imagine I have to use MVVM, so I have my view, viewmodel and model classes.
I bind the controls (textbox, button and textblock) from the view to the viewmodel on corresponding properties and commands. However, I'm not sure where the viewmodel functionality should end. For instance, would the following be a way to structure the application?
Model:
public class Model
{
public string Input { get; set; }
public string Output { get; set; }
public void FancyMethod ()
{
// Use input to calculate output
}
}
ViewModel:
public class ViewModel
{
public string Input {get; set;}
public string Output {get; set;}
public ICommand command {get; set;}
public Model model {get; set;}
public ViewModel()
{
model = new Model();
}
// When the button is pressed, model.input = Input and then execute model.FancyMethod()
}
If you want to keep a clean layer model, you should not include public Model model {get; set;} in your ViewModel.
So, for example, if you have a command, targeting some business model, your structure should be something like this:
//you don't have this one... but well, maybe other cases have
public class SomeService : ISomeService
{
//member of ISomeService
public void SomeFancyMethod(Model model)
{
//do stuff..
}
}
public class Model //might be database, or domain model.
{
public string Input { get; set; }
public string Output { get; set; }
}
As for your viewmodel, it will become something like this:
public class ViewModel
{
private ISomeService _someService;
//note: someService is passed through a IoC service like ninject, unity, autofac etc.
public ViewModel(ISomeService someService)
{
_someService = someService;
//initialize the command:
command = new RelayCommand(() =>
{
_someService .SomeFancyMethod(new Model()
{
//properties could be mapped with an automapper.
});
});
}
public ICommand command {get; private set;}
public string Input {get; set;}
public string Output {get; set;}
}
Note: there are some additional techniques involved:
using an inversion of control container, and pass the service
through the constructor.
abstracting the service by means of an
interface (ISomeService)
possibly some automapper to isolate your mapping from and towards Models/ViewModels
"So why make this so 'complicated'? You are just making a copy.", a commonly heard argument against this pattern:
Well:
it isn't complicated
doing this will separate your layers. This mean that changes in your datalayer doesn't break your View. In the long run, you'll benefit, as change will come and you'll need to maintain the code.
I guess the FancyMethod() contains your business logic and produces a value that you want to display in the view. In this case, FancyMethod() belongs to your model as it contains some business logic that is the same regardless of whether it's being executed in the context of a client application or some other component.
So your model would look something like this, i.e. it accepts an input and produces an output but it doesn't expose any properties that a view may bind to:
public class Model
{
public string FancyMethod(string input)
{
// Use input to calculate output
}
}
You could then inject your view model with the model and call the FancyMethod when the user executes the command by clicking on the Button in the view:
public class ViewModel
{
private readonly Model _model;
public ViewModel(Model model)
{
_model = model;
command = new RelayCommand(Execute, CanExecute);
}
public string Input { get; set; }
public string Output { get; set; }
public ICommand command { get; private set; }
private bool CanExecute(object _)
{
return !string.IsNullOrEmpty(Input);
}
private void Execute(object _)
{
Output = _model.FancyMethod(Input);
}
}
Obviously the view model class should also implement the INotifyPropertyChanged interface and raise change notifications to the view.
In short the business logic belongs to the model and the application logic, for example what happens when a user clicks a Button, belongs to the view model.
I think its not necessary to outsorce the Input and Output properties in another class. The reason for this is that the properties reflect the input and output of the view. So they have to be in the viewmodel.
You can outsorce the SomeFancyMethod in a service class to separate the logic from the viewmodel anlogous to mvc.

Generic class constraint where <T> is a type constraining the generic class

Perhaps not the most accurate title, but it's a little difficult to describe; perhaps you guys can help me out here? I'm writing a game using the MVC format, and I want each base class (controller, model, and view) to have a reference to their accompanying features, forming a sort of triangle (ie. A model has a reference to a controller that defines it, and a view that references it, etc. ) Much of these classes look like this:
public class Model {
public Controller controller;
public View view;
public void Connect (Controller controller, View view) {
this.controller = controller;
this.view = view;
}
}
This is okay, but whenever I intend to pull up a ChildModel's controller, I'll need to cast to the appropriate ChildController to obtain the correct version. I could make a utility method/getter to fetch an appropriately cast item, but I'd rather not rewrite this piece of code for each and every child class. I thought I could solve this issue by making the base classes generic, but now I'm running into an issue where the newly generic classes need references to the class that's trying to define them, hence:
public class Model<V, C> where V : View<?, C> where C : Controller<?, V> {
public Controller<?, V> controller;
public View<?, C> view;
public void Connect (Controller<?, V> controller, View<?, C> view) {
this.controller = controller;
this.view = view;
}
}
As you can see, this quickly gets messy in the base class. I don't know what symbol to place for (in reference to the example above) the Model that's attempting to define the constraints. Placing 'Model' into the question marks doesn't seem to compile either, as I run into a hellish boxing conversion issue.
Is there a way to accomplish what I'm after, or am I just trying to be too clever here? If this could work, I'd love to be able to declare child classes with the type constrained to their 'triangle', thus I could avoid needless casting or helper methods:
public class ChildModel<ChildView, ChildController> {
public ChildModel () {
this.controller <- calls ChildController type, not base type!
}
}
Anyone have any ideas?
It looks like you are confusing ownership with interactions. Ownership implies that one owns the other, while interactions imply how they communicate with one another. MVC primarily defines interactions between the three participants, though you could say that a view and controller both own a model.
In your code as shown, a class owns a property, therefore a controller class owns a view and a view owns a controller.
var model = new Model();
var view = new View<Controller<Model, View<Controller, Model>, ...
This doesn't work with generics in the way you would like because the interactions become circular. It is the chicken and the egg problem: chickens come from eggs which are laid by chickens. We can solve most of the problem by giving the controller ownership of the view, and both the controller and view ownership of a model.
public class Model
{
}
public interface IView<M>
{
M Model { get; }
}
public class MyView : IView<Model>
{
public MyView(Model model)
{
Model = model;
}
public Model Model
{
get;
}
}
public interface IController<V, M>
{
M Model { get; }
V View { get; }
}
public class MyController : IController<MyView, Model>
{
public MyController(MyView view, Model model)
{
View = view;
Model = model;
}
public Model Model
{
get;
}
public MyView View
{
get;
}
}
We still used generics to do this, and you have easy access to most of the information so far without introducing circular references.
class Program
{
public static void Main()
{
var model = new Model();
var view = new MyView(model);
var controller = new MyController(view, model);
}
}
Now if you want to make sure the view has a reference to the controller, you can do this via a property.
view.Controller = controller;
You could disregard everything I just showed you - and go the property injection route. This means instead of taking in the dependencies by the constructor, which creates circular reference restrictions on how the objects can be created, you can simply do this.
var model = new Model();
var view = new View();
var controller = new Controller();
model.View = view;
model.Controller = controller;
view.Controller = controller;
view.Model = model;
controller.View = view;
controller.Model = model;
Whatever method you use, the trick is to avoid the circular dependency issue that you have in your current code. Most MVC frameworks provide rich data binding which breaks the direct coupling between the classes, but if you don't have that, you have to either write something or find something, or work within the confinements of the language rules.
There are a lot of ways to solve this. As I wrote this there was another answer posted so you should also look at that.
Here's my suggestion.
1. You should use the Controller as the main part of your MVC pattern. The controller should get the information from the Mode, process it and then call the view.
Here's my base class for the Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Inheritance.Classes
{
public class Controller<T, U> where T : Model, new() where U : View, new()
{
protected T _model;
protected U _view;
public Controller()
{
this._model = new T();
this._view = new U();
}
public Controller(T model, U view)
{
this._model = model;
this._view = view;
}
public string ParentFunction()
{
return "I'm the parent";
}
}
}
Note, I have also a Model and View base class. Since they are empty for the moment, I won't show you the code
Then, I can define my child classes. For example, I will make a PageController, PageModel and PageView. They will all inherite from their BaseClass.
Note : Once again, PageModel and PageView are empty. They are only used for the inheritance
PageController.cs
using Inheritance.Page;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Inheritance.Classes
{
public class PageController : Controller<PageModel, PageView>
{
public PageController():base()
{
}
public PageModel Model
{
get
{
return base._model;
}
}
}
}
So as you can see, you will specify the Model class and the View class only inside the PageController.
To use your classes, you can do as follow :
PageController controller = new PageController();
//We can access the parent function
Console.WriteLine(controller.ParentFunction());
//Function defined into the controller.
PageModel model = controller.Model;
I think this is what you want:
public class GameModel : Model
{
public int ID { get; set; }
}
public class GameView : View<GameModel, GameView>
{
public float FOV { get; set; }
}
public class GameController : GameView.BaseControler
{
// Set ID
public GameController()
{
Model.ID=100;
View.FOV=45f;
}
}
class Program
{
static void Main(string[] args)
{
var gm = new GameModel();
var view = new GameView();
var ctrl = new GameController();
view.Connect(gm, ctrl);
Debug.WriteLine(view.Model.ID);
}
}
public class Model
{
}
public class View<TModel,TView> where TModel : Model where TView : View<TModel, TView>
{
public TModel Model { get; private set; }
public BaseControler Controler { get; private set; }
public void Connect(TModel model, BaseControler controler)
{
this.Model=model;
this.Controler=controler;
this.Controler.Connect(model, this as TView);
}
public class BaseControler
{
public TView View { get; private set; }
public TModel Model { get; private set; }
public void Connect(TModel model, TView view)
{
this.Model=model;
this.View=view;
}
}
}

Update models at runtime using mvvm

I'm familiar with MVVM and differences between models, viewmodels and views. The only thing that I'm not able to find answer to is how to update models at runtime. Simple example to show you what I mean:
Let's say I have application which can display graphs and store them in a database.
I have models
public class Session {
public Document Doc { get; set; }
}
public class Document {
public string Name { get; set; }
public Point[] GraphPoints { get; set; }
}
I can connect those to their viewmodels by passing them as parameters, so:
public class SessionViewModel{
private readonly Session _session;
public SessionViewModel(Session session)
{
this._session = session;
}
}
public class DocumentViewModel{
private readonly Document_document;
public SessionViewModel(Document document)
{
this._document = document;
}
}
public class ShellViewModel {
public SessionViewModel SessionVm { get; set; } // <-- Bind in view
public DocumentViewModel DocumentVm { get; set; } // <-- Bind in view
private Session _session;
public ShellViewModel()
{
_session = new Session();
session.Doc = new Document();
SessionVm = new SessionViewModel(session);
DocumentVm = new DocumentViewModel(session.Doc);
}
}
Problem appears when in the middle of my application's life cycle I decide to change value of document. For example:
public void OnNewDocumentLoaded(Document newDoc)
{
_session.Doc = newDoc;
}
_session.Doc was changed but every DocumentViewModel has its own instance of document which is passed in a constructor, so even though I changed model, my viewmodel stays the same.
Also I don't want to use INotifyPropertyChanged inside my model, because models should not know about framework and from my understanding this is a bad approach. Also I keep my models in PCL project so I'm not even able to implement INotifyPropertyChanged in my models.
From my understanding of a MVVM approach, models should not have a viewmodel associated with them. Instead, your views should have a viewmodel associated to them. Inside your viewmodel you can have objects from models in your application. Inside your viewmodel is where you should implement INotifyPropertyChanged. Those methods control the objects you have changed and then binding can occur between your view and viewmodel.

Categories