patterncsharpMinor
Trying MVVM on timer app
Viewed 0 times
tryingapptimermvvm
Problem
Check me:
Am I right?
I have written simple timer application, where I want to follow MVVM. There are
In
```
class Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
Timer myTimer;
int _time;
public int Time
{
get { return _time; }
set
{
_time = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Time"));
}
}
public Model(int time)
{
Model should do everything. That's where all functionalities and features are accommodated. It has some properties, that I can access and use. Theoretically, it could work as a standalone app (used via command prompt).View does nothing but looks (like a monitor: you always look at it, whereas the real work does your computer). ViewModel supply and modify Model's output to the View and View's user input to the Model.Am I right?
I have written simple timer application, where I want to follow MVVM. There are
ToggleButton whitch start or stop countdown and Slider to set time to count. ToggleButton's content shows remaining time.View
In
View's code behind I instantine ViewModel and set DataContext on it.ViewModelclass ViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
Model MyModel;
public ICommand Command
{ get; }
public string TimeString
{
get
{
int timeInMin = MyModel.Time / 60;
return timeInMin != 0 ? timeInMin + " min" : MyModel.Time + "s";
}
}
public int TimeInMs
{
get
{
return MyModel.Time;
}
set
{
MyModel.Time = value;
}
}
public ViewModel()
{
MyModel = new Model(3600);
Command = new ToggleCommand(MyModel.Start, MyModel.End);
MyModel.PropertyChanged += (a,b)=> { PropertyChanged(this, new PropertyChangedEventArgs("")); };
}
}Model```
class Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
Timer myTimer;
int _time;
public int Time
{
get { return _time; }
set
{
_time = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Time"));
}
}
public Model(int time)
{
Solution
IMHO You are pretty much right and definitely on the right track; but, in my experience of working with multiple enterprise application ranging from medium to very large WPF application -
there is no definite boundary to differentiate between Model, ViewModel, and View; it's more like Agile, it gives you guidelines and direction but is pretty much flexible to adapt as per your needs.
Here's my take on your points -
Model should do everything. That's where all functionalities and
features are accommodated. It has some properties, that I can access
and use. Theoretically, it could work as a standalone app (used via
command prompt).
Mostly yes, that's the main idea of Model. A model can also have methods to update model data and behavior. It's not at all dependent on anything related to a view.
View does nothing but looks (like a monitor: you always look at it,
whereas the real work does your computer).
Not always true, a view is supposed to do everything related to a view. You can have a lot of requirements where you need to do things to have a user-friendly view and do data conversions to use/modify VM data and create itself (e.g. Converters). It's especially true when you work with third party controls, you need to write a lot of code in view to make them work or achieve trivial things.
Remember that only View in MVVM knows(*can know) about other two entities i.e. VM and Model.
ViewModel supply and modify Model's output to the View and View's user
input to the Model.
Yes, VM works as a mediator but most imp. thing is that it should also be independent of view; similar to Model it should also be capable to support another type of view or multiple views (e.g. WPF and SL and WP). So it should not have anything specific to a particular type of view.
Now regarding
MyModel.PropertyChanged += (a,b)=> { PropertyChanged(this, new
PropertyChangedEventArgs("")); };
This is very subjective to type of application and size of Model; In your example its not a bad thing to do, but in case you had 15-20 properties in your Model and same number of properties in ViewModel to expose them to view, and 10-15 such Models and VM's - then its a totally different game altogether.
Having such uncontrolled change notifications can cause huge performance problems as your view might get updated again and again unnecessarily or take a long time to render due to multiple passes of rendering cycles.
Most importantly it will never be in your full control, it will be very hard to debug and understand why and when UI is updated.
There are two options -
This is highly debatable and a topic of discussion; I would recommend you to read these related SO threads -
In MVVM should the ViewModel or Model implement INotifyPropertyChanged?
In MVVM model should the model implement INotifyPropertyChanged interface?
Another minor but important point, you should always consider having an equality check for every property firing property change i.e. before updating your
there is no definite boundary to differentiate between Model, ViewModel, and View; it's more like Agile, it gives you guidelines and direction but is pretty much flexible to adapt as per your needs.
Here's my take on your points -
Model should do everything. That's where all functionalities and
features are accommodated. It has some properties, that I can access
and use. Theoretically, it could work as a standalone app (used via
command prompt).
Mostly yes, that's the main idea of Model. A model can also have methods to update model data and behavior. It's not at all dependent on anything related to a view.
View does nothing but looks (like a monitor: you always look at it,
whereas the real work does your computer).
Not always true, a view is supposed to do everything related to a view. You can have a lot of requirements where you need to do things to have a user-friendly view and do data conversions to use/modify VM data and create itself (e.g. Converters). It's especially true when you work with third party controls, you need to write a lot of code in view to make them work or achieve trivial things.
Remember that only View in MVVM knows(*can know) about other two entities i.e. VM and Model.
ViewModel supply and modify Model's output to the View and View's user
input to the Model.
Yes, VM works as a mediator but most imp. thing is that it should also be independent of view; similar to Model it should also be capable to support another type of view or multiple views (e.g. WPF and SL and WP). So it should not have anything specific to a particular type of view.
Now regarding
MyModel.PropertyChanged += (a,b)=> { PropertyChanged(this, new
PropertyChangedEventArgs("")); };
This is very subjective to type of application and size of Model; In your example its not a bad thing to do, but in case you had 15-20 properties in your Model and same number of properties in ViewModel to expose them to view, and 10-15 such Models and VM's - then its a totally different game altogether.
Having such uncontrolled change notifications can cause huge performance problems as your view might get updated again and again unnecessarily or take a long time to render due to multiple passes of rendering cycles.
Most importantly it will never be in your full control, it will be very hard to debug and understand why and when UI is updated.
There are two options -
- Explicitly expose Model properties, indirectly through your VM and update them only when required; that's a lot of work and hard to maintain.
- As your Model implements INotifyPropertyChanged, directly use Model properties in View (through VM i.e. exposing your MyModel object in VM) and your view and model will always remain in sync.
This is highly debatable and a topic of discussion; I would recommend you to read these related SO threads -
In MVVM should the ViewModel or Model implement INotifyPropertyChanged?
In MVVM model should the model implement INotifyPropertyChanged interface?
Another minor but important point, you should always consider having an equality check for every property firing property change i.e. before updating your
Time property in Model you should check if the new value is different then existing one or not and only fire property change if its a different value.Context
StackExchange Code Review Q#146262, answer score: 2
Revisions (0)
No revisions yet.