MVVM - Model vs ViewModel - where to put my code? - c#

Im creating a small application for managing online racing leagues.
For this i will have a database that accesses data from web and exposes data objects through interface. The database doesn't exist yet but i created a Mockup which uses local XML files as datasource.
Small example for a league interface:
public interface ISchedule
{
string Name { get; set; }
List<IRaceSession> Races { get; }
// and some more properties …
IRaceSession AddRace();
void RemoveRace(IRaceSession race);
// and some more Methods …
}
public interface IRaceSession
{
uint RaceId { get; }
DateTime Date { get; set; }
TimeSpan Duration { get; set; }
// and some more properties …
}
Now to get this into my WPF with MVVM pattern i created a Model for each object the database is exposing and implemented the INPC there.
*Note: ContainerModel<> and ObservableModelCollection<> are classes i created to handle updates from the database while still keeping the INPC intact.
public class ContainerModel<T>
{
T Source { get; set; }
public ContainerModel(T source)
{
Source = source;
}
void UpdateSource(T source)
{
// handle updates …
}
}
public class ScheduleModel : ISchedule, ContainerModel<ISchedule>
{
public string Name { get => Source.Name ; set { Source.Name = value; NotifyPropertyChanged(); } }
public ObservableModelCollection<RaceSessionModel, IRaceSession> Races { get; }
List<IRaceSession> ISchedule.Races => Source.Races
public ScheduleModel(ISchedule source) : base(source)
{
Races = new ObservableModelCollection<RaceSessionModel, IRaceSession>(Source.Races);
}
IRaceSession AddRace()
{
Races.Add(// new Race Object);
}
void RemoveRace(IRaceSession race)
{
Races.Remove(// select race object to remove);
}
}
public class RaceSessionModel : IRaceSession, ContainerModel<IRaceSession>
{
public uint RaceId => Source.RaceId;
puglic DateTime Date { get => Source.Date; set { Source.Date = value; NotifyPropertyChanged(); } }
TimeSpan Duration { get => Source.Duration; set { Source.Duration = value; NotifyPropertyChanged(); } }
//--> here come some more logic im not sure About:
TimeSpan DurationHours
{
get => Duration.Hours;
set
{
// set only Hours componennt of Duration
Duration = Duration
.Subtract(Duration.Hours)
.Add(value);
NotifyPropertyChanged();
}
TimeSpan DurationMinutes
{
get => Duration.Minutes;
set
{
// set only Minutes componennt of Duration
Duration = Duration
.Subtract(Duration.Minutes)
.Add(value);
NotifyPropertyChanged();
}
}
Then i have a viewModel and a view that binds to the Model properties directly.
public class SchedulerViewModel : ViewModelBase //<-- just a Basic implementation of INPC
{
private ScheduleModel _schedule;
public ScheduleModel Schedule { get => _schedule; set { _schedule = value; NotifyPropertyChanged(); } }
public SchedulerViewModel(ScheduleModel schedule)
{
Schedule = schedule;
}
// Commands and other properties communicating with the view
// …
}
Now with this design i have a few concerns coming up. I am still in the process of getting my head around the whole design pattern and it is the first time i am Building it up from Scratch.
My Models don't really contain data, but only expose properties from the database
Am i Right in thinking that this is actually something a viewModel should do?
As you can see my models also hold some Kind of calculation for property Input. Should this "Business logic" be put outside the model too? Or would that also be better put in a ViewModel?
After all im doubting what i present are "models" at all. Would it be Right to call them ViewModels and then act with the Object from the database as the model?
*Edit:
When i began with this i read that for each View you should supply only one ViewModel, which is why i created my classes like this. But im not sure anymore if this is correct.

It may depend largely on what you're attempting to do with the application, but generally I would approach it like this:
Model for Schedule
Model for RaceSession
ViewModel for RaceSession, containing a RaceSession Model
ViewModel for Schedule containing a Schedule Model a collection of
RaceSessionViewModels
I've always regarded models as pretty much just representing a row from a database, essentially; a basic data entity that exists on its own outside of the application. The ViewModel is then anything that is relevant only within the application.
The reason I wouldn't have a collection of RaceSession Models in the Schedule Model, would be that if you were to do any kind of application-based manipulation of the RaceSessions, that's something that belongs in a ViewModel, so you'd then sort of be looking at a Schedule Model, with a collection of RaceSessionViewModels. So I'd keep Models strictly as single data entities, without any kind of entity relationships (joins) built in - these kinds of relationships, I'd build in to the ViewModel layer. Even if you didn't need a ViewModel for RaceSession, I'd still have a collection of RaceSession Models within the Schedule ViewModel.
As an example of the above, I believe that the AddRace method really belongs in the Schedule ViewModel, rather than the Schedule Model.
With regards to the TimeSpan calculations, I'd probably have the Hours and Minutes as get only properties (on the RaceSession ViewModel), with other methods on a RaceSessionViewModel that alter the Duration property directly. The exact implementation of this would depend on whether or not you were actually changing these in the database when they update.
Some Example Pseudocode
public class RaceSession : INPC
{
INPCProperties
RaceSession(inpcProperties)
{
INPCProperties = inpcProperties;
}
}
public class RaceSessionViewModel : INPC
{
public RaceSession RaceSession { get; set (INPC); }
public int Hours => RaceSession.Duration.Hours;
public RaceSessionViewModel(raceSession)
{
RaceSession = raceSession;
}
private void SetDurationHours(int hours)
{
RaceSession.Duration =
Duration
.Subtract(Duration.Hours)
.Add(hours);
NotifyPropertyChanged("Hours");
}
}

For the transfer of Data from the Model to the ViewModel, I would create simple Objects (Dto - DataTransferObject) without (or very minimal) Logic.
A good rule of thumb is that you want unsaved Data in the ViewModel while saved Data - or data that is about to be saved - belongs in the Model.
//--> here come some more logic im not sure About:
TimeSpan DurationHours
{
get => Duration.Hours;
set
{
// set only Hours componennt of Duration
Duration = Duration
.Subtract(Duration.Hours)
.Add(value);
NotifyPropertyChanged();
}
TimeSpan DurationMinutes
{
get => Duration.Minutes;
set
{
// set only Minutes componennt of Duration
Duration = Duration
.Subtract(Duration.Minutes)
.Add(value);
NotifyPropertyChanged();
}
I would put these into the ViewModel. In the Model you want the whole Timespan Object, only the ViewModel should be aware of the restrictions that you can only set them separately in the View.
When i began with this i read that for each View you should supply
only one ViewModel, which is why i created my classes like this. But
im not sure anymore if this is correct.
Yes, it saves a lot of headache later on, when you have to maintain your code and make changes which only apply to a single View.

No. A viewmodel connects the data (the models not the database) with the view. But it neither manipulates the view nor the database.
I wouldn't leave that in the models. This kind of stuff belongs actually in the viewmodel.
In every view you can have multiple viewmodels to present, but you definitely need at least one to begin with.
I suggest, as you already started constructing your MVVM, that you now look up an example in the internet somewhere that implements this design pattern. I suppose you already read some of the theory behind it.

Related

how to ensure that the editing (IsEdited or whatever) state of an EFCore entity is notified

I've got a class Invoice that has InvoiceRows.
public class Invoice
{
[Key]
public int? Id { get; set; }
public DateTime InvoiceDate {
get => invoiceDate;
set => PropertySet<DateTime>(value, ref invoiceDate);
}
private DateTime invoiceDate;
public List<InvoiceRow> Rows { get; } = new List<InvoiceRow>();
[NotMapped]
public bool IsEdited { get; set; } = false;
public void PropertySet<T>(T value, ref T field)
{
if (value.Equals(field)) return;
field = value;
IsEdited = true;
}
}
The Invoice is edited in a WPF graphical interface that need notifications when the invoice has been edited in order to activate the save button, for example.
(In a first implementation i thought that IsEdited was a viewmodel thing and I omitted it from the model and included in the viewmodel instead. Turns out to be quite complex when handling sub-records. However I've not yet fully realized which option the model or the viewmodel implementation is best, and this is possibly a second question.)
The IsEdited is easily managed at record level, but how to handle it at the InvoiceRow level?
The first idea that comes to mind is to notify back to the main record.
This in turn requires additional code to wire up notifications between Invoice and Rows.
Another idea is to leverage the DbContext state that holds in one place the required information instead of gathering it around sub-records.
Are there any other options left? One of the challages of such decision is to fully evaluate the consequences of each approach before hand. What are the pros/cons of different ways of handling this?
In my little experience of WPF I've read something about hirearchical viewmodels. Maybe they are suitable for this, handling the wrap-up at the viewmodel level?

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.

How to code/design the Model part in Caliburn.Micro?

I am new to MVVM pattern and Caliburn.Micro. I've read some tutorials on how to get started, but I'm confused about the Model part of MVVM in the context of Caliburn.
I want to create my first MVVM application and I have some design questions:
In tutorials, the Model was presented as simple property in
ViewModel. How should I manage more complex models? Is there any
naming convention? Obviously, there should be some external classes
made for my models, but how should I communicate between my models
and the view?
How should I keep references to many instances of one complex model?
For ex. cumtomers (instances of Customer model class)
Is there a possibility to manipulate one model class in many
ViewModels? How should I store my model reference, so it'll be
visible from different ViewModels?
Where should I put my code for more complex model manupulation/file,
database storage? How should I invoke such code? I'm not asking here
about SQLConnections, but MVVM best practices. :)
Thanks in advance for any help :)
EDIT:-------------------------------------------------------
Thank you for your anwser. I uderstand the topic more clearly, but I'm still confused about some details.
For an example, let's assume this little application. I have a form that allows me to add a new Customer. It has a few fields like Name, Surname etc.
After pressing the button, I invoke the addCustomer command in the ViewModel. I want my program to store the newly created customer inside the database.
My view also has the List control (whatever), which displays my customers as raw strings (like "Name: John, Surname: Doe, Address: ..." I know it's dumb to make it like this, but i need an example of model manipulation (like .toString()))
For this example, I've created a bunch of stuff to illustrate my vision of that process:
fields - it's a set of form fields like Name, Surname etc.
customerSet - it's a set of Customer class to store all created
customers
.addToDatabase(fields) - a method which puts newly created customer
to the database
.getStrings - a method which prepares a set of strings to be
displayed by the list in CustomerView
I think about 2 approaches that would be good for a solution:
First approach. I don't like this one. The only advantage is, that
ViewModel handles all the logic inside application. Sharing model
would be a serious problem here, because saving methods are bound to
the ViewModel class.
Second, MVC like approach. To me it's the most intuitive one. But - I
don't know where should I store CustomersModel object, so few
ViewModels could have access to it.
Which is the better one? Or maybe another approach that is more suitable for MVVM?
Another problem is: Where should I put my method that will load all the Customers from the database, so they could be displayes on the list? In "get method" inside viewmodel, or inside a model class?
In tutorials, the Model was presented as simple property in ViewModel.
How should I manage more complex models? Is there any naming
convention? Obviously, there should be some external classes made for
my models, but how should I communicate between my models and the
view?
Your models should represent whatever it is they need to whether it's a customer, account, etc. The view models job is to handle the interaction between the view and models.
How should I keep references to many instances of one complex model?
For ex. cumtomers (instances of Customer model class)
Generally, you will map complex models to more friendly format for display, you can do it manually or use a tool like AutoMapper.
Is there a possibility to manipulate one model class in many
ViewModels? How should I store my model reference, so it'll be visible
from different ViewModels?
If you're working with a local db you can pass IDs around. If it's a service you could persist the model locally for other view models to work with. You could also inject a singleton, ISharedData, into view models that need to work with shared data.
Where should I put my code for more complex model manupulation/file,
database storage? How should I invoke such code? I'm not asking here
about SQLConnections, but MVVM best practices. :)
Create services for more complex model manipulation / business logic. Inject the services into view models that require them. ICustomerService, IAccountService, etc.
EDIT:-------------------------------------------------------
You're first approach is correct. To your point about sharing the model being a serious problem because saving methods are bound to the view model class. The view model will have a SaveCustomerCommand that is fired when the button is clicked, because of its binding.
The SaveCustomerCommand will persist the CustomerModel, regardless of how the CustomerModel is persisted. So if its a database, the view model might have a reference to a context and issue a _db.Save(CustomerModel). If another view model needs to manipulate a CustomerModel, it will do so by using the context. The view model could also have a reference to a CustomerService that handles the crud for the CustomerModel.
Here's how this might look:
public class AddCustomerViewModel : Screen
{
private readonly ICustomerService _customerService;
public AddCustomerViewModel(ICustomerService customerService)
{
_customerService = customerService;
}
//If button is named x:Name="SaveCustomer" CM will
//bind it by convention to this method
public void SaveCustomer(Customer customer)
{
_customerService.Save(customer);
}
}
public class CustomerListViewModel : Screen
{
private readonly ICustomerService _customerService;
private List<CustomerDisplayModel> _customers;
public CustomerListViewModel(ICustomerService customerService)
{
_customerService = customerService;
}
public List<CustomerDisplayModel> Customers
{
get { return _customers; }
set
{
_customers = value;
NotifyOfPropertyChange();
}
}
//only fires once, unlike OnActivate()
protected override void OnInitialize()
{
var customers = _customerService.LoadAllCustomers();
//could just use the model but this shows how one might map from
//the domain model to a display model, AutoMapper could be used for this
Customers = customers.Select(c => new CustomerDisplayModel(c)).ToList();
}
}
public interface ICustomerService
{
List<Customer> LoadAllCustomers();
void Save(Customer customer);
}
//same as button, Label named x:Name="CustomerName" will bind
// to CustomerName
public class CustomerDisplayModel
{
private readonly Customer _customer;
public CustomerDisplayModel(Customer customer)
{
_customer = customer;
}
public string CustomerName
{
get { return _customer.Name; }
set { _customer.Name = value; }
}
public string Surname
{
get { return _customer.Surname; }
set { _customer.Surname = value; }
}
public string Address
{
get { return _customer.Address; }
set { _customer.Address = value; }
}
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Address { get; set; }
}

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).

Is it OK to have some logic codes inside a property of a data model class?

I am learning MVC 3 and I have not found people using some logic codes inside a property of a data model class.
They do the data model class as follows (for example):
public class Customer
{
public int CustomerId {get;set;}
//other properties without any logic code.
}
Is it ok to have logic codes inside a property as follows?
public class Customer
{
private int customerId;
public int CustomerId {
get{return customerId;}
set
{
customerId=value;
// some logic codes go here.
}
}
//other properties go here.
}
Edit 1:
This is my real scenario:
Child table data model:
namespace MvcApplication1.Models
{
public class Choice
{
public int ChoiceId { get; set; }
public string Description { get; set; }
public bool IsCorrect { get; set; }
public QuizItem QuizItem { get; set; }
}
}
Parent table data model:
namespace MvcApplication1.Models
{
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
set
{
choices = value;
foreach (var x in choices)
x.QuizItem = this;
}
}
}
}
Consumer:
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var data = new List<QuizItem>{
new QuizItem
{
QuizItemId = 1,
Question = "What color is your hair?",
Choices = new Choice[]{
new Choice{ ChoiceId=1, Description="Black.", IsCorrect=true},
new Choice{ ChoiceId=2, Description="Red.", IsCorrect=false},
new Choice{ ChoiceId=3, Description="Yellow.", IsCorrect=false}
}
},
new QuizItem
{
QuizItemId = 2,
Question = "What color is your noze?",
Choices = new Choice[]{
new Choice{ChoiceId=1, Description="Pink.", IsCorrect=false},
new Choice{ChoiceId=2, Description="Maroon.", IsCorrect=true},
new Choice{ChoiceId=3, Description="Navy Blue.", IsCorrect=false}
}
}
};
return View(data);
}
}
}
This calls for a method. Two reasons why:
I don't recommend setters for Collections
Property Usage Guidelines - Setting a property for each item in collection every time property is set is expensive and should not be in a property. A method is preferred instead.
Code (that you have in your case) in setter causes enough side-effects to disqualify use of property
Setters for collection type properties - A discussion on StackOverflow regarding setters for collections.
I suggest following:
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
}
public void SetChoices(IEnumerable<Choice> choices)
{
foreach (var x in choices)
x.QuizItem = this;
this.choices = choices;
}
}
I think this logic you should implement in controller. However I always define POCO classes in my model and use ViewModel to implement such simple logic.
This is more of a realm of philosophical approach. As such it is up to a debate.
Today by far the most prevalent approach is to use strict layered approach of separation of concerns where "model" objects are only responsible for containing data and if you want to apply any sort of business logic on top of that, you need to implement that on a separate "business logic" layer, which handles application of such concerns as validation/vewrification of the integrity of data, mutation of data according to a business processes, etc.
Another approach is to use model layer to actually model (as in verb) the business of the target domain. In this case, the model acts as a direct definition of the business rules and should just as rich as rules of the business require it to be. (this approach has been taken to extreme by Naked Objects, that basically keeps data structures as well as business logic in the model and generates ORM, controller logic and views from the same model)
Generally the question of "how smart can/should be my model objects" is one to ask from the frameworks you use. Some frameworks simply don't care either way (ASP.NET MVC), others want you to never worry about coding this stuff, as long as you provide enough metadata so that they can do their job for you (NHibernate, Entity Framework). Others yet encourage you to express all your business rules and logic in the domain object model (e.g. Naked Objects)
In my opinion, a data model should be doing logic related to data (value) as in "is this value a valid data to...?". Also when doing hidden logic like in this case "attaching a parent", naming the method to just "set" is also wrong.
A sample of a more complex data model:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application

Categories