Update models at runtime using mvvm - c#

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.

Related

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.

Update Observable Collection When Item Added to Model C# wpf

Ok so I'm fairly new to this. I followed along with this MVVM tutorial from YouTube. It was pretty good and straightforward. Basically it sets up a very basic program with a Model class, DataAcess class, 3 viewmodels (Main window, Employee and ViewModelBase) and finally a view which has a stackpanel and a couple of text boxes that are bound to the FirstName and LastName in the Model.
It all works how it's meant to and I have been through it a number of times and I'm pretty sure I understand how it all works but the trouble that I am having is adding new Employees.
In the DataAccess class (Employee Repository) Employees are added as shown below.
class EmployeeRepository
{
readonly List<Employee> _employee;
public EmployeeRepository()
{
if (_employee == null)
{
_employee = new List<Employee>();
}
_employee.Add(Employee.CreateEmployee("Bob", "Jones"));
_employee.Add(Employee.CreateEmployee("Sarah", "Marshall"));
_employee.Add(Employee.CreateEmployee("Peter", "Piper"));
}
public List<Employee> GetEmployees()
{
return new List<Employee>(_employee);
}
}
And in the Model there is a method call CreateEmployee as such
public class Employee
{
public static Employee CreateEmployee(string firstName, string lastName)
{
return new Employee { FirstName = firstName, LastName = lastName };
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
So I thought I would add a button to the MainWindow and then add another name to the list. Hopping the view would update as an item is updated. Just to see if it would work I just used the code behind.
I thought I could just add a new employee the same way I did in the EmployeeRepository so I tried this
readonly List<Employee> _employee = new List<Employee>();
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
_employee.Add(Employee.CreateEmployee("John", "Smith"));
}
I have tried many many ways of doing this, to no avail. I have watched and read many tutorials and questions, but nothing that I have tried as worked.
What am I missing? I initially thought that it was not working because I am adding the item to the List in the repository, but not to the ObservableCollection that is in the viewmodel. And the AllEmployees ObservableCollection is the ItemSource for view.
readonly EmployeeRepository _employeeRepository;
public ObservableCollection<Model.Employee> AllEmployees
{
get;
private set;
}
public EmployeeListViewModel(EmployeeRepository currentWindowRepository)
{
if (currentWindowRepository == null)
{
throw new ArgumentException("currentWindowRepository");
}
_employeeRepository = currentWindowRepository;
this.AllEmployees = new ObservableCollection<Model.Employee>(_employeeRepository.GetEmployees());
}
But in the button code I tried to implement something similar, but no.
I can also add the view xaml code and MainViewModel codes so that you can see how it's all bound if you like.
Thanks in advance for any help!
You can't do it in "one operation".
When you add a new Employee in the UI, you first need to instantiate your Employee class and add it to the observable collection.
If in valid state, then persist it to in the repository.
private ICommand addEmployeeCommand;
public ICommand AddEmployeeCommand { get { return addEmployeeCommand; } }
public ObservableCollection<Employee> Employees { get; protected set; }
private void AddEmployee()
{
// Get the user input that's bound to the viewmodels properties
var employee = Employee.Create(FirstName, LastName);
// add it to the observable collection
// Note: directly using model in your ViewModel for binding is a pretty bad idea, you should use ViewModels for your Employees too, like:
// Employee.Add(new EmployeeViewModel(employee));
Employees.Add(employee);
// add it to the repository
this.employeeRepository.AddOrUpdate(employee);
}
// in constructor
this.addEmployeeCommand = new DelegateCommand(AddEmployee, CanExecuteAddEmployee);
As noted, avoid directly using your model inside the ViewModel bindings, it has several disadvantages, like you view now depend on your viewmodel. each and every change in the model needs to be reflected in the view, this beats the purpose of a viewmodel which is meant to decouple view, viewmodel and model.
Another disadvantage is, that typically your models are do not implement INotifyPropertyChanged and this will cause memory leaks in the view.
In your EmployeelistViewModel you are creating ObservableCollection , and you think that it will get repopulated automatically upon addition/deletion of employees. secondly in your GetEmployees method you are creating a new list. you should use obser.coll directly in place of List (_employee). And return this ocoll from your method.
One solution to this is to add INPC to your models and to then have your view models watch their models and update themselves accordingly i.e. something like this:
public class MyListType
{
// some data
}
public class MyModel
{
public IList<MyListType> MyListItems { get; set; }
public MyModel()
{
this.MyListItems = new ObservableCollection<MyListType>();
}
}
public class MyListTypeViewModel : ViewModelBase
{
public MyListType Model {get; set;}
// INPC properties go here
}
public class MyViewModel
{
public IList<MyListTypeViewModel> MyListItemViewModels { get; set; }
public MyViewModel(MyModel model)
{
(model.MyListItems as INotifyCollectionChanged).CollectionChanged += OnListChanged;
// todo: create initial view models for any items already in MyListItems
}
private void OnListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// create any new elements
if (e.NewItems != null)
foreach (MyListType item in e.NewItems)
this.MyListItemViewModels.Add(new MyListTypeViewModel{Model = item});
// remove any new elements
if (e.OldItems != null)
foreach (MyListType item in e.OldItems)
this.MyListItemViewModels.Remove(
this.MyListItemViewModels.First(x => x.Model == item)
);
}
Now your list of view models will automatically stay synched with your list of models. The main problem with this approach is that your models will typically originate from your ORM (database) code, so you will need to work with whatever framework you're using to inject INPC at creation time e.g. if you're using NHibernate then you'll need to use a binding interceptor for INPC and a collection convention to make the lists ObservableCollections.

MVVM Model with Entity Framework

I have a Prototype using WPF + MVVM + PRISM + ENTITY FRAMEWORK
The problem is that im very confuse if i use the ENTITY FRAMEWORK Entities as the Model of the MVVM pattern. I have a Business Logic Layer, and i had problems using mappers on this layer, because im very unhappy on the conversion (Map problem).
What i can do to simplify the code, use a real Model not the Entitie object(for me use the Entitie as model is incorrect on the frontend), with the MVVM pattern on mind... and stay good for changes on the future, it will have 200+ entities on the final version...
Thats my layers...(Please forget about Mapping, since i taked it off putting the EF entities on the ViewModel, but the image represents the correct layers)
Im not using the repository too since i can add it on the end with changes only on the BLL.
VIEW MODEL:
my current prototype do a getall, put it on a grid, and on selectchanged of the grid i put selected item on the textbox, and the save button update this changes to the database.
public class CadastroClienteViewModel : BindableBase, ICadastroClienteViewModel
{
private readonly IClienteBLL _clienteService;
#region Model
//public Cliente ObCliente { get; private set; }
public int ClienteID
{
get { return ((Cliente)cliItems.CurrentItem).ClienteID; }
set
{
((Cliente)cliItems.CurrentItem).ClienteID = value;
OnPropertyChanged("ClienteID");
}
}
public string Nome
{
get { return ((Cliente)cliItems.CurrentItem).Nome; }
set
{
((Cliente)cliItems.CurrentItem).Nome = value;
OnPropertyChanged("Nome");
}
}
#endregion
public CadastroClienteViewModel(IClienteBLL ServiceCliente)
{
//ObCliente = new Cliente();
_clienteService = ServiceCliente;
this.SaveCommand = new DelegateCommand(ExecuteMethodSave);
this.RefreshCommand = new DelegateCommand(ExecuteMethodRefresh, CanExecuteMethodRefresh);
RefreshCommand.Execute(null);
}
private void ExecuteMethodSave()
{
_clienteService.ClienteBLL_Update(((Cliente)cliItems.CurrentItem));
RefreshCommand.Execute(null);
}
private bool CanExecuteMethodRefresh()
{
return true;
}
private void ExecuteMethodRefresh()
{
var personViewModels = _clienteService.ClienteBLL_GetAll();
//cliente = new ObservableCollection<Cliente>(personViewModels);
cliItems = new ListCollectionView(personViewModels.ToList());
cliItems.CurrentChanged += CliItemsOnCurrentChanged;
//OnPropertyChanged("cliente");
OnPropertyChanged("cliItems");
}
private void CliItemsOnCurrentChanged(object sender, EventArgs eventArgs)
{
//OnPropertyChanged("ObCliente");
}
public ICommand SaveCommand { get; private set; }
public ICommand RefreshCommand { get; private set; }
//public ObservableCollection<Cliente> cliente { get; private set; }
public ICollectionView cliItems { get; private set; }
}
MODEL(Im not using it... but i would like):
public class MCliente
{
public int ClienteID { get; set; }
public string Nome { get; set; }
}
EF Entitie:
namespace Sistema.DataEntities.Models
{
public class Cliente
{
public Cliente()
{
}
public int ClienteID { get; set; }
public string Nome { get; set; }
}
BLL:
public class ClienteBLL : IClienteBLL
{
readonly ISistemaContext _context;
public ClienteBLL(ISistemaContext context)
{
_context = context;
}
public IEnumerable<Cliente> ClienteBLL_GetAll()
{
return _context.Cliente.AsEnumerable();
}
public Cliente ClienteBLL_GetByID(int id)
{
return _context.Cliente.Find(id);
}
public bool ClienteBLL_Adicionar(Cliente Obcliente)
{
_context.Cliente.Add(Obcliente);
return _context.SaveChanges() > 0;
}
public bool ClienteBLL_Update(Cliente Obcliente)
{
_context.Cliente.Attach(Obcliente);
_context.Entry(Obcliente).State = EntityState.Modified;
return _context.SaveChanges() > 0;
}
public bool ClienteBLL_Delete(int id)
{
var clubMember = _context.Cliente.Find(id);
_context.Cliente.Remove(clubMember);
return _context.SaveChanges() > 0;
}
I'm adding this as an answer (not a comment) even if it's not a final answer to your question (cause it's opinion-based) but it doesn't fit as a comment. That's just what I would do for a WPF application that requires a database.
I would entirely drop the idea of directly connecting your WPF application to your database. I would build a 3-tiers architecture, i.e. I would create a stateless webservice that does all the stuff on server side.
So you would have:
the database
the webservice (using WCF), that is connected to the database, that does all the data stuff for you (I would even make it responsible of the business stuff too)
the WPF application, that is connected to the webservice:
the View layer is your XAML + your code-behind
the ViewModel layer is, well, your ViewModels (out of scope of your question, but feel free to ask if you have any question about that layer). The ViewModels asynchronously call the webservice
the Model is the client WCF proxy
Some benefits of this approach:
depending on the hardware/network harchitecture, could be a huge performance benefit to only make ONE call to the server instead of N calls (assuming the latency between the DB and the webservice (both on "server side") is lower than the one between the WPF application and the database)
more scalable
all benefits of the stateless approach: one Entity Framework context instantiation per webservice requests, so much easier to deal with concurrency issues (in case you have N WPF instances running concurrently)
easier to maintain (loose coupling between tiers)
easier to test (assuming you actually build tests)
better security (no need to expose a direct access to the database over the network)

C# MVVM: Adding new ViewModel (strict non-exposed Model design)

I've been working on an MVVM application in C# but consistiently run into some problems when working with the collections of ViewModels my View digests. Specifically, they all tend to relate to the issue of the Model being a private member of the ViewModel.
An example of this is creating new ViewModels (as requested by the View). For some preamble (although you might not need these to help me) here are example Model and ViewModel classes:
Private Class Model()
{
public string Name { get; set; }
}
Public Class ViewModel()
{
Private Model _Model;
Public Void ViewModel(Model model)
{
_Model = model;
}
Public String Name
{
get
{
return _Model.Name;
}
set
{
_Model.Name = value;
}
}
}
The entire model is never directly exposed as a public member of the ViewModel. The MainWindowViewModel handles collections of Models (private, the view cant see these) and ViewModels (public for View digestion):
Public Class MainWindowViewModel
{
Private List<Model> _NamesModel;
Private ObservableCollection<ViewModel> _NamesViewModel;
Public Void MainWindowViewModel()
{
//Lets pretend we have a service that returns a list of models
_NamesModel = Service.Request();
foreach(Model model in _NamesModel)
{
ViewModel viewmodel = new ViewModel(model);
_NamesViewModel.Add(viewmodel);
}
}
Public ObservableCollection<ViewModel> NamesViewModel
{
get
{
return _NamesViewModel;
}
}
}
Now thats the preamble but now I have a problem. How do I add a new ViewModel? Do methods within my view create a new ViewModel and populate that? Being a purist, I'm assuming the View should not be allowed to create or populate Models at all. Should my ViewModel contain a constructor that accepts nothing (i.e. no underlying model) and instead creates a blank to populate?
These kinds of issues keep coming up with a "pure" MVVM approach. I've had to create a public method in my ViewModel (bool compare(Model model)) that will compare a model (ready for deletion etc.) to it's internal one. If the models were publicly exposed (breaking purity) then it would be much easier to do stuff like find the ViewModel thats connected to a Model.
I can sympathize with some of those problems. I recently wrote an MVVM application where similar questions came up frequently. One of the tricks is to decide - definitively - which class is going to be responsible for Model instances. Do you want it to be your MainWindowViewModel? Or your NameViewModel? You don't want to share the responsibilities of creating/deleting the model between both of those classes; you'll have quite a logistical nightmare.
Secondly, even a "pure" MVVM approach doesn't dictate that you can't expose the model publicly. You said yourself that doing so would save you a lot of headache: DO IT. MVVM dictates only that the ViewModel has no knowledge/access of the View. There are many "official" MVVM examples that go so far as to implement their Model using the INotifyPropertyChanged interface, and bind directly to properties on the Model.
Personally, I think I would dictate control of the NameModel to the NameViewModel. This means that you should remove the list of NameModels completely from the MainWindowViewModel. If you want to give the NameViewModel an optional constructor which takes a Model, that would be fine too.
I'm a fan of this approach:
public NameViewModel : ViewModelBase
{
public NameModel Model
{
get { /* get stuff */ }
set { /* set stuff */ }
}
// Default constructor creates its own new NameModel
public NameViewModel()
{
this.Model = new NameModel();
}
// Constructor has a specific model dictated to it
public NameViewModel(NameModel model)
{
this.Model = model;
}
//Model wrapper properties
public String Name
{
get { return Model.Name; }
set { Model.Name = value; }
}
}
and...
public class MainWindowViewModel
{
Private ObservableCollection<ViewModel> _NameViewModels;
Public Void MainWindowViewModel()
{
//Lets pretend we have a service that returns a list of models
var nameModels = Service.Request();
foreach(Model model in nameModels)
{
ViewModel viewmodel = new NameViewModel(model);
NameViewModel.Add(viewmodel);
}
}
Public ObservableCollection<ViewModel> NameViewModels
{
get
{
return _NameViewModels;
}
}
}
In this way your MainWindowViewModeldoesn't keep an entirely separate copy of the Models; it only tracks the NameViewModels. Each NameViewModel is responsible for its own underlying model, while still making the option available to have a specific model passed to it during construction.
All the creation-related issues can be resolved with introduction of factory design pattern. The factory will take care of creating view models basing on model that was provided.
public class MainWindowViewModel
{
private List<Model> _NamesModel;
private ObservableCollection<ViewModel> _NamesViewModel;
private IViewModelFactory factory;
public void MainWindowViewModel(IViewModelFactory factory)
{
//Lets pretend we have a service that returns a list of models
_NamesModel = Service.Request();
_NamesViewModel = factory.CreateNamesViewModels(_NamesModel);
}
public ObservableCollection<ViewModel> NamesViewModel
{
get
{
return _NamesViewModel;
}
}
}
What is more, you could even get rid of Service dependency in view model and move it to the factory itself, thus reducing the need to keep model in view model (admittedly though, removal of model might not work in more complex scenarios):
public ObservableCollection<ViewModel> CreateNamesViewModels()
{
var models = Service.Request();
return new ObservableCollection(models.Select(m => new ViewModel(m)));
}
Also, your main window view model can expose commands that utilize factory to create any new instances. This way, no model is leaking to view and also no creation details are exposed (since commands will hide actual implementation).

Categories