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
}
Related
I need to connect methods in View (WPF window) to events in ViewModel. Is it violation of MVVM pattern to DirectCast Object DataContext in view to concrete VM type and connect its events? If yes, is there better way to do it?
First look at what the methods in the view do. If they manipulate the view, consider adding properties to the viewmodel that you change in the events in the viewmodel and bind the view to. This way, by binding the view to properties you eliminate the need for code in the view.
If the methods contain other logic consider moving that logic to the viewmodel.
In other cases casting a DataContext to a viewmodel or interface can be a valid option and is not a violation of the MVVM pattern.
When adding code to a view, do consider testing. Automated/unit testing a view is harder than testing a viewmodel.
It is not a violation of the MVVM pattern, but the more abstract the better, of course (not because of MVVM but as a general good practice).
If you're setting your DataContext on XAML, you may be able to keep it abstract by using Interactivity EventTrigger and CallMethodAction... Maybe. But if you're setting it on code-behind (via injection or whatever), you're left with either casting the DataContext to a known type, or using Reflection (I wouldn't >_>).
Generally, creating an interface for your ViewModel, so you keep a decent level of abstraction and only expose what the view needs to know instead of its whole implementation, is good enough for most scenarios.
public interface IMyViewModel
{
event EventHandler MyEvent;
}
public class MyViewModel : IMyViewModel
{
public event EventHandler MyEvent;
// More viewmodel related stuff
protected virtual void OnMyEvent(EventArgs e)
{
if (MyEvent != null)
MyEvent(this, e);
}
}
public class MyWindow : Window
{
public MyWindow(IMyViewModel viewModel)
{
this.DataContext = viewModel;
InitializeComponent();
(this.DataContext as IViewModel).MyEvent += MyEventHandler;
}
private void MyEventHandler(object sender, EventArgs e)
{
// Do view related stuff
}
}
Using MVVM pattern and WPF, I would like to bind my controls to two properties. Let's say I have a label that is bind to property on VM1 and I would like to bind it as well to the property on VM2 to send received value from VM1 to VM2.
I could use messenger and for multiple items Tuple Class, but I was wondering if there is another solution for that. Multibinding? but then I need ValueConverter.
Thank you for any suggestions.
Since The View-Model is an abstraction of the view that exposes public properties and commands, it doesn't make a lot of sense for a view to have two view-models the way you explained. It'll be more rational if there is a VM class as the view-model of your view that has two properties of type VM1 and VM2. Then the binding would be on VM.VM1.YourText and you can notify VM2 via events like this:
in VM1:
public event EventHandler<EventArgs> ValueChanged;
string _yourText;
public string YourText
{
get
{
return _yourText;
}
set
{
_yourText= value;
if (ValueChanged != null)
ValueChanged(_yourText, new EventArgs());
}
}
In VM:
public VM1 Vm1 {get; set;}
public VM2 Vm2 {get; set;}
public VM()
{
InitializeComponent();
Vm1 = new VM1();
Vm2 = new VM2();
Vm1.ValueChanged += Item_ValueChanged;
DataContext = this;
}
void Item_ValueChanged(object sender, EventArgs e)
{
VM2.YourAnotherText = sender.ToString();
}
If 2 properties are connected, usually INotifyPropertyChanged can be utilized to notify about a change of 2 or more properties if on the same ViewModel.
What I understand is that you want also to notify a View attached to a ViewModel about a change of a property on another ViewModel. This is usually done by letting ViewModels exchange information.
If that's a one rare case, using message bus for that might be an overkill. Usually keeping a reference to each view model and changing properties from outside should be all right. To keep separation of concerns you can create an interface on one or both viewmodels and reference this interface instead of a concrete type.
Overall keeping a single binding between a control and property keeps it simple and easy to understand and you should worry about making sure that this property handles all changes to/from other VMs.
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.
I'm dealing with a big problem for developing my app. It's a Winforms base application on C# implementing the Model-View-Presenter pattern, but I am new to this method. I've searched everywhere and haven't found an answer to my issue.
I need to know how I can use this pattern to allow communication between winforms, and how the presenter must show them without coupling the presenter to the form. I've seen a way using Factory pattern, but don't understand how to implement it.
Any help or point in the right direction would be appreciated.
Assertion
The Presenter is responsible for coordination between the View and Model (if following the Passive View implementation).
This could look like:
A View instantiating the Presenter and injecting itself into the Presenter:
IPresenter presenter;
public View() { presenter = new Presenter(this) }
A Presenter instantiating one or more views and injecting itself into the view(s):
IView1 view1;
public Presenter() { view1 = new View1(this) }
IView1 view1;
IView2 view2;
public Presenter() { view1 = new View1(this); view2 = new View2(this); }
Example
In your case, a Presenter coordinating multiple views might look something like this (pseudo):
public class Presenter : IPresenter
{
IView1 view1;
IView2 view2;
public Presenter()
{
view1 = new View1(this);
view2 = new View2(this);
}
private WireViewEvents()
{
view1.OnButtonClick += HandleButtonClickFromView1;
}
public void HandleButtonClickFromView1()
{
view2.SetSomeData();
view2.Show();
}
In this example, an event raised by View1 is handled by the Presenter, data is set in View2, and View2 is shown.
Keep in mind that no matter what your implementation is, the goals of MVP are:
Separation of concerns (UI seperate from domain logic).
Increasing testability.
Keep that this is just a basic example of how a Presenter might coordinate multiple views. If you want to abstract your View creation from the presenter you might move the creation into another container that the Presenter calls in to to create Views and subscribe to their events.
In MVP ,winforms should not communicate with each other.
Form A knows its Presenter A,
Form B knows its presenter B
Usually , you will modify model with form A through Prensenter A. Presenter B will listen to model changes,and will refresh Form B accordingly
If you need more coordination, you may consider using an Application Controller
See http://dotnetslackers.com/articles/designpatterns/The-Presenter-in-MVP-Implementations.aspx
I am just showing a dummy code in which 2 views are trying to communicate to each other through Presenter using interfaces. It is a simple example and let mw know if something is breaking. I have not tested this code to be honest.
namespace WindowsFormsApplication1
{
internal class View1 : IView1
{
public View1()
{
new Presenter(this);
}
public string Username { get; set; }
public event EventHandler ShowDetails;
}
}
namespace WindowsFormsApplication1
{
internal class View2 : IView2
{
public View2()
{
new Presenter(this);
}
public string Position { get; set; }
}
}
namespace WindowsFormsApplication1
{
public class Presenter
{
private readonly IView1 _view1;
private readonly IView2 _view2;
public Presenter(IView1 view1)
{
_view1 = view1;
_view1.ShowDetails += ShowDetails;
}
private void ShowDetails(object sender, EventArgs e)
{
_view2.Position = _view1.Username == "My Name" ? "Arhchitect" : "Project Manager";
}
public Presenter(IView2 view2)
{
_view2 = view2;
}
}
}
public interface IView1
{
string Username { get; set; }
event EventHandler ShowDetails;
}
public interface IView2
{
string Position { get; set; }
}
But after this example some notes. To start with your application try to decide first weather you want to go with 1 View interface or 2. There may be chances and even ease if you can use a single interface.
I think the points made earlier about the model raising events to make a presenter aware of changes is correct. I do have a couple comments I hope will be useful.
First, the View implementation might not be a single form. Sometimes, it makes sense for part of the model to be maintained by a separate (probably modal) form that really acts like a complex control in the View. In that case, the interaction between the forms would be direct. The Presenter should not care how the View implementation is done.
Second, when it looks like forms need to interact that are not clearly part of the same view (a lookup form, for example) I would recommand using the Application Controller pattern. In this case, when Form A needs to perform a function (like, "Find Product" or "Edit Details") it will call a method on it's own Presenter to do that. The Presenter then calls a separate method on the Application Controller (which all Presenters reference, it's a singleton) and the Application Controller opens the requried form which has its own Presenter. In WinForms, this could all be done with a modal form, in which case the results are sent back through the call chain. Alternatively, some event raising between the Application Controller and Presenters would be needed - i.e. the Presenter raises events on the Application Controller about what it has done and other Presenters substribing to that event are thus notified.
More on the Application Controller pattern in MVP can be found on my blog post Using the MVP 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.