INotifyPropertyChanged for model and viewmodel - wpf

I am currently away from home (and will be for a few more weeks) and only have a tablet - therefore, I have no access to Visual Studio to test what I'm trying to learn - the MVVM pattern.
So far, I think the theory is set, but I'm confused about the INotifyPropertyChanged interface.
I think one of the ideas of the MVVM pattern is to be able to update the Model which in turn notifies the ViewModel which in turn notifies the view. If I'm wrong then the rest of this question is meaningless.
My question is, do all the classes have to share 1 implementation of INotifyPropertyChanged?
In other words, which is correct:
A property name is the same for all classes (but each class has it's own unique implementation of INotifyPropertyChanged)
A property name is the same for all classes (and each class inherits from a single base class which implements INotifyPropertyChanged)?

No, they don't have to share anything. However the implementation of INotifyPropertyChanged is some lines of code, so we usually made a base class for models - like BaseModel or BaseViewModel which implemented INotifyPropertyChanged.
The implementations are generally specific to the version of C# language you use (the older ones works in the newer version of language).
Look here: http://jesseliberty.com/2012/06/28/c-5making-inotifypropertychanged-easier/
but instead of having the Employee class to implement the INotifyPropertyChanged, you can implement it in a base class
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
and then the Employee class from the blog should look like this
public class Employee : BaseViewModel
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged();
}
}
}
this is for C# 5 (the .Net 4.5 - the one which does not run on Windows XP)

Related

Meaning of POCO classes in MVVM and Entity Framework

I am trying to understand how WPF binding works in junction with MVVM and Entity Framework. So far I understand databinding as a concept related to properties. However, when it gets to EF I lose understanding of which objects to use to define the Model for database. For instance, I have a Model class for a Category:
public class Category : INotifyPropertyChanged
{
string _CategoryId;
public string CategoryId
{
get
{
return _CategoryId;
}
set
{
if (_CategoryId != value)
{
_CategoryId = value;
RaisePropertyChanged("CategoryId");
}
}
}
string _CategoryName;
public string CategoryName
{
get
{
return _CategoryName;
}
set
{
if (_CategoryName != value)
{
_CategoryName = value;
RaisePropertyChanged("CategoryName");
}
}
}
/// <summary>
///
/// </summary>
/// <param name="prop"></param>
void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
and POCO version:
public class CategoryPoco
{
public CategoryPoco() { }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
Properties of the non Poco class in my understanding can be then used in databinding. However, I also need to build the database context model:
public DbSet<Category> Categories { get; set; }
Now here is where I lose my understanding, do I use Poco or non-Poco classes when building the context model?
How do I match the two classes when I start exchanging data with the Database?
You use the "POCO version" to build the context model for your database. If you will, POCO is just defined as
Plain Old CLR Object.
Just a normal class, no attributes describing infrastructure concerns or other responsibilities that your domain objects shouldn't have.
so technically, your Category is also considered as POCO. POCO doesn't have a different meaning when used with MVVM or EF. EF just uses those objects to map it back to the database.
In your Category class, I normally don't create another Model class just to have that INotifyPropertyChanged. It's more flexible and clear that your Category class should be called CategoryViewModel.
If I read your code and I see an INotifyPropertyChanged interface where WPF uses it also for DataBinding, then I would be against it as you are now using Model -> View pattern without the ViewModel as your middleman. (Assuming you use category as your binding source)
If you decided that you need to extend Category class, then I would suggest to use T4 template to generate your POCO Classes as a partial class, and create another partial class that implements INotifyPropertyChanged or add more properties that are not in the columns of a given table e.g., CategoryStatus, CategoryDescription and mark those properties with [NotMapped] attribute.
That way you don't have to do matching between the two classes and mostly your Model is already setup in the ViewModel to communicate it back with EF. You also have the flexibility to add more functionality to the object, which complies with the Open-Closed design principle.

Using WPF design data with the MVVM pattern

I'm using the MVVM pattern in our WPF application to allow for comprehensive unit testing. The MVVM pattern itself is working great, however I'm struggling to adapt the pattern in a way that means I can use the design-time data support of WPF.
As I'm using Prism the ViewModel instances are generally injected into the constructor of the view, like so
public MyView(MyViewModel viewModel)
{
DataContext = viewModel;
}
Dependencies for the ViewModel are then injected into the constructor, like so
public class MyViewModel
{
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// Read-only properties that the view data binds to
public ICollectionView Rows { get; }
public string Title { get; }
// Read-write properties are databound to the UI and are used to control logic
public string Filter { get; set; }
}
This is generally working really well except when it comes to design data - I wanted to avoid compiling design-data specific classes into my released assembly and so I opted to use the {d:DesignData} approach instead of the {d:DesignInstance} approach, however in order for this to work correctly my ViewModel now needs to have a parameterless constructor. In addition, I also often need to change additional properties either to have setters or to be modifiable collections in order to be able to set these properties in XAML.
public class MyViewModel
{
public MyViewModel()
{
}
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// My read-only properties are no longer read-only
public ObservableCollection<Something> Rows { get; }
public string Title { get; set; }
public string Filter { get; set; }
}
This is worrying me:
I have a parameterless constructor that is never intended to be called and isn't unit tested
There are setters for properties that only the ViewModel itself should be calling
My ViewModel is now a jumbled mixture of properties that should be modified by the view, and those that shouldn't - this makes it tricky to tell at a glance which piece of code is responsible for maintaining any given property
Setting certain properties at design time (e.g. to see styling on the Filter text) can actually end up invoking ViewModel logic! (so my ViewModel also needs to be tollerant of otherwise mandatory dependencies being missing at design time)
Is there a better way to get design-time data in a WPF MVVM application in a way that doesn't compromise my ViewModel in this way?
Alternatively should I be building my ViewModel differently so that it has more simple properties with the logic separated out somewhere else.
First, I would recommend you to have a look at this video where Brian Lagunas provides several best practices about MVVM. Brian is - at least - involved in the development of Prism, as his name appears in the nuget packages information. Didn't check further.
On my side I only use bits of Prism, and my Model and ViewModel always offer blank constructors (like what Brian shows), the data context is assigned in the view's XAML, and I set the properties values like :
<MyView.DataContext>
<MyViewModel />
</MyView.DataContext>
and
public void BringSomethingNew()
{
var myView = new View();
(myView.DataContext as ViewModel).Model = myModel;
UseMyView();
}
Another benefit with this approach is that the ViewModel is created once, with the same path at design and run time, so you create less objects and save GC efforts. I find this elegant.
With regards to the setters, the design data will still work if you make them private, like:
public string MyProp { get; private set; }
Ok, customize it to manage NotifyPropertyChange at your convenience, but you've got the idea.
Now, I don't have yet a solution to manage ObesrvableCollections (I face the same problem, although putting multiple values in XAML sometimes work... ???), and yes, I agree that you have to manage the case when the properties are not set, like setting default values in the constructor.
I hope this helps.
I too have worked with NUnit testing with WPF and MVVM implementation. However, my version is reversed from yours. You are creating the view first, then creating the model to control it.
In my version, I create the MVVM model FIRST and can unit test it till the cows come home and not worry about any visual design... if the model is broken, so too will the visual implementation.
in my MVVM model, I have a method to "GetTheViewWindow". So, when I derive from my MVVM baseline, each view model has its own view its responsible for. So via a virtual method, each instance will do its own new view window when being applied for production.
public class MyMVVMBase
{
private MyViewBaseline currentView;
public MyMVVMBase()
{ // no parameters required }
public virtual void GetTheViewWindow()
{ throw new exception( "You need to define the window to get"; ) }
}
public class MyXYZInstanceModel : MyMVVMBase
{
public override void GetTheViewWindow()
{
currentView = new YourActualViewWindow();
}
}
Hope this helps as an alternative to what you are running into.

WPF MVVM Single ViewModel for Display and Editing

I am using the example from Josh Smith. He has a WorkspaceViewModel which display a list of CustomerViewModels. He is using the same ViewModel for displaying all Customers and for editing one single customer.
Is this a good practice? If I have a list of CustomerViewModels I dont need the SaveCommand or the CloseCommand or some IsSelected Flag.
Is it better to have a seperate EditCustomerViewModel? But how to deal with Workspace related stuff? For example:
public class Workspace : ViewModel
{
public ICommand CloseCommand;
}
public class AllCustomers : Workspace
{
public ObservableCollection<CustomerViewModel> CustomerViewModels;
}
// Option A (one ViewModel for display and edit):
public class CustomerViewModel : ?
{
public string CustomerName;
public ICommand SaveCommand;
}
Or seperation:
// Option B:
public class CustomerViewModel : ViewModel
{
public string CustomerName;
}
public class EditCustomerViewModel : Workspace
{
public CustomerViewModel CustomerViewModel;
public ICommand SaveCommand;
}
// Option C (CustomerViewModel does not need CloseCommand but EditCustomerViewModel does):
public class CustomerViewModel : Workspace
{
public string CustomerName;
}
public class EditCustomerViewModel : CustomerViewModel
{
public ICommand SaveCommand;
}
Edit:
I try to clarify my problem. In the CustomerViewModel in the example of Josh Smith, he has Commands for closing and saving a customer. In the AllCustomerView he has a GridView that binds to a ObservableCollection of CustomerViewModels. But in the GridView the both commands are not necessary. In the GridView I can ignore both commands, but is that a good design?
I'm not quite sure what you mean as a quick look at that article shows that he is using both a list and a view/edit view modal called AllCustomers­ViewModel and CustomerViewModel respectively. Which would certainly be the recommended practise rather than using a single view model which has more than one responsibility.
Both of these view models inherit from WorkspaceViewModel which adds his workspace functionality. So, in summary, I would follow his pattern if you want to build something similar. You should also seriously consider an MVVM framework such as Caliburn.Micro which adds easy convention based view composition as well as screen life cycle.

MVP in Winforms

I'm primarily from an ASP.Net background with some MVC. I've also done a little Silverlight and MVVM, however I'm now about to move into Winforms which I have very little experience of, so I'm wondering how to tackle MVP.
Typical MVP samples show the presenter setting a view property (via some kind of IView interface), with the concrete view putting that property value into a textbox for example. Instead of this archaic approach, can one utilise INotifyPropertyChanged in MVP, and if so how? A very quick example would be really useful!
If I was to create a model that implemented INotifyPropertyChanged then isn't this more like MVVM? (i.e. the presenter updates the model, and via the magic of INotifyPropertyChanged the view gets updated). Yet everywhere I've read about MVVM and Winforms, people say it isn't suitable. Why? My understanding is that you can databind just about any control's property, so what's Winforms missing? I'm trying to understand the shortcomings of databinding in Winforms compared to WPF, and why MVVM can't be used, as it seems simpler to implement than MVP.
Thanks in advance
Andy.
I have just checked up how data binding in WinForms uses INotifyPropertyChanged.
The data binding through the BindingSource does really support INotifyPropertyChanged if the DataSource object of the BindingSource or model property corresponding to DataMember implements this. You can use M. Fowlers supervising presenter / controller to full extent here:
You don't even need a hand-written code, the BindingSource synchronizes the view with the model properties in both directions (model -> view and view -> model), and if the model supports INotifyPropertyChanged then the view will be updated automatically.
The code constructs I have used so far:
During view initialization:
this.bindingSource.DataSource = this.presenter;
Designer-generated code:
this.textBoxPhone.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.bindingSource, "Model.Phone", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
The model class:
public class Customer : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName == value)
return;
_firstName = value;
NotifyPropertyChanged("FirstName");
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
if (_lastName == value)
return;
_lastName = value;
NotifyPropertyChanged("LastName");
}
}
private string _company;
public string Company
{
get { return _company; }
set
{
if (_company == value)
return;
_company = value;
NotifyPropertyChanged("Company");
}
}
private string _phone;
public string Phone
{
get { return _phone; }
set
{
if (_phone == value)
return;
_phone = value;
NotifyPropertyChanged("Phone");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
The presenter class:
public class CustomerPresenter
{
public CustomerPresenter(Customer model)
{
if (model == null)
throw new ArgumentNullException("model");
this.Model = model;
}
public Customer Model { get; set; }
public ICustomerView View { private get; set; }
}
Try to find examples of Supervising Controller MVP flavor, I use that with WinForms, very successfully I would say. The entities support INotifyPropertyChanged, presenter binds them to the view, and presenter subscribes to the PropertyChanged event so that it knows when view changed something (dirty checking). View is responsible only for binding data, all other functionality is moved to the presenter.
You don't miss anything. MVVM is very suitable with WinForms. Microsoft only encoureges the use of WPF and MVVM pattern with it.

MVVM for collections

I have recently started learning wpf and am trying to use mvvm.
My understanding is that in the mvvm neither the view or the model should know the other exists.
What I am trying to do is show a list of customers on the screen. But if I code the viewModel as shown below. which is similar to many examples I see on the net, then I end up with some code looking like this
class Customer
{
public String Name {get;set;}
public String Address {get;set;} }
}
class MainWindowViewModel
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
public ObservableCollection<Customer> Customer
{
get {return customers;}
}
public MainWindowViewModel()
{
//cust1 and cust2 are Customer objets
customers.Add(cust1);
customers.Add(cust2);
}
}
Now if I create an instance of my MainWindowViewModel and set it as the datacontext of my MainWindowView (my view) and i further bind the viewmodels Customers property to a listBox, then the view will need a reference to the assembly that contains my Models.
So my questions are.
1) Is adding a reference to Models assembly allowable in MVVM, since this would mean the view knows about the model.
2) would a better solution be to wrap each Customer object in a CustomerViewModel and have the MainWindowViewModel contain ObservableCollection of CustomerViewModel
instead of ObservableCollection of Customer. This would separate the models completely from the view.
I'm not sure why you think the project containing your views requires a reference to your model project? There is nothing in your view which references your models directly - your binding expressions in XAML are linked by name only, and to properties on your view model anyway, not your model.
Wrapping your model in a view model is a good option if your view requires additional data than your model provides, and it is undesirable to change your model. For example, you view may need to display the Age of a User type, but User only has a DateOfBirth property. Creating a UserViewModel with an Age property would be a good option if you didn't want to alter your model.
Answers to your questions:
What is bad about the View referring the Model? This is absolutely ok when it simplifies the code. Just the other way around (Model -> View) is bad practice.
You don't need to wrap each Customer object in a CustomerViewModel when you don't have special needs. I would suggest to follow a pragmatic way and keep the code simple.
You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF) which shows the scenario you describe here.
We usually create a CustomerViewModel. That is enforced by our generic CollectionViewModelBase class. This unsures that every part the user interface uses is exspecially created to be displayed and we don't have any UI related code in the models which are often serializable POCOs.
The MVVM pattern is similar to any other MVx pattern (MVC, MVP, ...) in that it encourages separation of concerns (SoC), which in turn improve maintainability / testability of your code. Beyond the usual SoC, MVVM gives the following:
Unit testing of your view logic; this is because you move logic from your view into your view-model, making your view as dumb as possible.
Developer-designer workflow; because the view is 'dumb', it is easier to work with the XAML without the logic behind it.
Regarding visibility, i.e. what is visible to what, it is strictly as follows:
Model <= ViewModel <= View
In other words, the ViewModel can see the Model, but the Model cannot see the ViewModel. Likewise, the View can see the ViewModel, but not vice-versa.
Because the ViewModel has no reference to the View, it enables your code to be executed without any view components present, this enables (1) above.
The purpose of your ViewModel is to 'shape' your Model to make binding to the View easier. If your View is simple, then it is quite acceptable to do the following:
Model <= View
This still allows (1) unit testing, (2) developer-designer workflow.
It is also fine to use a hybrid approach, sometimes exposing your Model to your view, other times wrapping it in a ViewModel. For example:
http://www.scottlogic.co.uk/blog/colin/2009/08/the-mini-viewmodel-pattern/
Please don't create a bunch of boiler-plate ViewModel code, just because you think you have to!
You will definitively want to wrap your models in view only objects like below :
/// <summary>
/// Business model object : Should be in your separate business model only library
/// </summary>
public class BusinessModelObject
{
public string Prop1 { get; set; }
public int Prop2 { get; set; }
}
/// <summary>
/// Base notifying object : Should be in your GUI library
/// </summary>
public abstract class NotifyingObject<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, e);
}
private static readonly PropertyChangedEventArgs ModelPropertyChanged = new PropertyChangedEventArgs("Model");
private T _model;
public T Model
{
get { return _model; }
set
{
_model = value;
NotifyPropertyChanged(ModelPropertyChanged);
}
}
}
/// <summary>
/// Model decorator : Should be in your GUI library
/// </summary>
public class BusinessModelObjectAdapter : NotifyingObject<BusinessModelObject>
{
public BusinessModelObjectAdapter(BusinessModelObject model)
{
this.Model = Model;
}
private static readonly PropertyChangedEventArgs Prop1PropertyChanged = new PropertyChangedEventArgs("Prop1");
private string _prop1;
public string Prop1
{
get { return Model.Prop1; }
set
{
Model.Prop1 = value;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
private static readonly PropertyChangedEventArgs Prop2PropertyChanged = new PropertyChangedEventArgs("Prop2");
private int _prop2;
public int Prop2
{
get { return Model.Prop2; }
set
{
Model.Prop2 = value;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
//and here you can add whatever property aimed a presenting your model without altering it at any time
}

Resources