I am very new to WPF.
I am trying to figure out pros/cons of various architecture patterns in WPF, while creating an application designed to interact with a database.
The application begins with a master window, which contains various buttons which load other windows which each perform CRUD operations on different tables within that DB.
I am wondering about the merits and disadvantages of 3 possible approaches:
1) Instantiate a new entity instance within the constructor for each window
2) Each window have a have a constructor which supports dependency injection of the entity object. Every time the master window instantiates a new window object, it injects its own instance of the entity.
3) As per WPF Data Binding Walkthrough Create public ObjectResult properties on a class which inherits from application, and link to this/these properties in the
<Window.Resources><CollectionViewSource>
Tag of the various windows.
Thanks
Dependency Injection is the best option giving you most flexibility...
However, you shouldn't inject something as specific as the entity object but some service provider instead which would be a specific implementation of a service Interface and would not use the entity object directly but a Model instead which would abstract away the data access specifics giving you loose coupling benefits...
Related
What I'm trying to do is to get two WPF UIs running on two separate computers to share state. I'm thinking to have a service running on one of the two computers hold the MVVM model objects and the two UIs can then be clients of this service, databinding to objects that live in the service. I want to be able to propagate property changes from one UI to the other. So for example, if I have a property bound to a textbox in UIOne and the same property on the same object bound to a label on UITwo, then when I type into UIOne's textbox, the text in UITwo's label updates.
I looked into using WCF for the service, but that looks like it won't work because WCF doesn't allow clients to access object references across service boundaries. And the simplest way I can imagine propagating INotifyPropertyChanged between UIs is by sharing the object by reference. So then I looked at .NET Remoting and it looks like it will allow you to share a .NET object between AppDomains.
But now I'm confused because I thought WCF replaces Remoting.
Am I misunderstanding how Remoting shares objects by reference? Would databinding to a .NET remoting object work the way I'm planning?
Does WCF really replace Remoting? Is there a way to use WCF to share an object between clients? I don't want to start using a "legacy" technology if the new one will work for me.
Is there a third option I should be considering?
I have developed a Microsoft Prism 4.0 application and I am struggling to understand how to make the user application setting functionality available to modules.
e.g. a Properties.Settings.Default.MyProperty.
I can define a simple class that gets populated via the bootloader (which does have a handle to the properties) and inject that into the modules but If I want to save a change of property, I need believe I need a handle to the Properties.Settings context which is not available to my modules (which are simple class libraries).
Your scenario sounds like the perfect reason to use a "Service" class. Create an interface and class called IUserSettingsService and UserSettingsService that has the information (or can load and save it from where it is stored).
Read Chapter 3 of the Prism 4.0 help file, Managing Dependencies Between Components, Registering Types with (either Unity or MEF, depending on what you are using as your DI Container).
Then, in your ViewModel that needs the user settings, locate and use your service. In MEF, it is as simple as adding a property of type IUserSettingsService with an [Import] attribute, or using [ImportingConstructor] and having a parameter of type IUserSettingsService. With Unity, you access the service through the container. See Chapter 10 of the Prism help file - Advanced MVVM Scenarios.
Added after comment discussion:
Because you need your service to be in the context of your main application, you can implement your service class there. Create the interface for your service in a shared library that can be used by both the main project and your modules. Finally, load the service in the bootloader class instead of in a module.
If I am generating POCO objects from EntityFramework, and using these to go to/from the WCF server, is there any reason to create client-side Models for the Views & ViewModels to use instead of just using the POCOs directly?
Almost all the MVVM examples I have looked at bind straight to the object returned from the WCF service. Is this good practice? Are there arguments that can be made for actually mapping the POCO to a Model and having the Views/ViewModels working with the Model object instead of the POCO?
The main reason I could think of is validation, however since the EF POCOs are partial classes, they can be expanded on to include validation.
EDIT
Most answers so far have brought up INotifyPropertyChanged as the main reason to build a separate Model. Does your answer change if you are using Self-Tracking entities instead of POCOs which already includes INotifyPropertyChanged? STEs are also partial classes which can be expanded upon to include validation.
Validation is the main reason not to bind directly to a POCO. In addition, if the POCO doesn't already implement INotifyPropertyChanged and other required interfaces, the experience working with the object on the WPF side may be less desirable, and implementing a ViewModel to wrap this makes sense.
Providing a ViewModel to wrap your POCO allows you to encapsulate the logic into ICommand implementations as well as implement required interfaces cleanly.
I disagree only slightly with Reed (an unusual circumstance to be sure). I would NOT implement a ViewModel to wrap the POCO. I would implement a Model class to wrap the POCO and expose the Models to the ViewModel via a Service layer.
The ViewModel's primary job is to appropriately present Model data to the View and react to its requests. The architecture I'm working on for this looks like so:
1 ViewModel for each View
The ViewModel calls a Data Service layer object to retrieve Model instances (not to be confused with a WCF service)
The Data Service layer issues the appropriate CRUD requests to the backend (this uses WCF, RIA, or RESTful Services for Silverlight but could be ADO.NET or EF directly for WPF).
The Data Service uses the returned POCOs to create Model objects.
Model objects wrap the POCO object and implement INotifyPropertyChanged. Model objects enforce business rules.
I'm still working through the details but I will be publishing something more concrete in the near future.
My Models accept a WCF object which exposes those properties which I wish to use in my ViewModel. I can then also extend the object as needed. My properties point to the WCF object's property and when I have to send the object back to the WCF service, I don't have to do any more work. The models inherit INotifyPropertyChanged and INotifyDataErrorInfo which the DTOs (mentioned here as POCOs) will not have. Your business logic / validaton exists in your Silverlight application and not in your WCF Service.
The View binds to the ViewModel which has a Model (or an observable collection of Models). The Models have a WFCObject which is a DTO (mentioned here as POCO). I use my ViewModel to communicate with the service, MVVM Light has the models communicate with the service / provider - which I don't like.
Bind to EF POCOs if you want to do simple CRUD or you want to make something fast.
Otherwise, your server-side models will tend to be very closely related to the database, which changes very slowly, as compared to user interface. For less trivial UI, you'll find yourself putting more and more kludges just to fit your database model into UI (or otherwise, which is even worse).
Also, there are performance issues (e.g. would you like to transmit whole entity when for UI you need only couple of properties?), and maintenance issues (e.g. if you would like to validate premium customer's order quite differently from ordinary one).
See also http://ayende.com/Blog/archive/2010/08/06/data-access-is-contextual-a-generic-approach-will-fail.aspx
Rachel's POCO's are just dumb objects generated by EF and used for transport (DTO). Therefore, they shouldn't have other things cluttering up their domain. This is a very nice way of designing your code because it decouples any client-side requirements from those on the server-side. That's why MVVM exists - to extend the MVC model incorporating those concerns.
There is no reason you can't bind to them in your views as long as you are not modifying them directly. You can add functionality to them by adding a partial class but I wouldn't even do that. In that case you should follow the MVVM design tenants and separate those into model objects that serve your needs in the client. This will be quite automated once you hook up INotifyPropertyChanged events to notify your views.
We are about to start up a new project similar to a previous one. I could just copy the old design but I am not all too satisified with the old design.
It is a "standard" business system (sales,stocktaking,warehousing etc) built ontop of .Net 3.5 (Winforms MDI) with Entity Framework in the backend.
All forms inherit from a baseform (which inherits Windows.Form). The form exposes a property called ObjectContext, which on the first call instantiates a new ObjectContext. This makes up a pretty good UnitOfWork i think, having all data-access isolated in each form.
However.
I have encapsulated all queries and common CRUD in "poor mans repositories". These Repositories are exposed as properties of the ObjectContext.
So if I wanted to bind and order to a form I would call
OrderLinesGrid = ObjectContext.OrderRepository.GetOrderLinesByID(orderID).
The OrderRepository gets a reference to the objectcontext created for the form, like this
(In my partial ObjectContext class)
Private _OrderRepository as OrderRepository
Public ReadOnly Property OrderRepository as OrderRepository
Get
if _orderrepository is nothing then
_orderrepository = New OrderRepository(me)
end if
return _orderrepository
End Get
End Property
What I do not like about this is:
The call to the repository is made
through ObjectContext. Hence, I do
not get abstraction between the
query and the dataaccesslayer I
would like.
For each new type in my Domain I
need to create a property in my
ObjectContext
My call to OrderRepository should just return domain objects and not worry about how it is persisted. Also, I cannot have each Repository have it's own ObjectContext since that would require me to Attach and Detach objects when referencing i.e Country to a Order.Country property.
I would appreciate any ideas and feedback on this design :)
I suggest you research "onion" principle , Repository pattern and Luw pattern.
There are many examples on the web.
Essentially you use POCO Model Core Project. No references to DAL project.
You declare interfaces for the Repository and luw patterns in the CORE project.
So Now a
UI layer -> instantiate context and DAL Object eg repository -> inject into CORE services.
Also connected to this approach is Inversion of Control or dependency injection pattern.
If you use test driven development against Dummy Repositories you can make sure the design principles are adhered to.
Following on from this initial investigations on Silverlight architectures, I have some new requirements to consider.
We expect our Silverlight client UI to be graphically heavy, with a GIS interface, multiple charts, gauges and datagrids arranged in a Widget style fashion. New widgets will be dynamically generated by the user.
Suppose a user wanted to dynamically create a chart widget from an existing datagrid widget pre-populated with data. It appears to me that if we were using a MVVM pattern with the view model on the server, this would result in an unnecessary call back home when the required data is already located in the client.
Now obviously the server needs to know about this new chart widget on the client, but how do I create the widget in the client first (with the existing client side data) and then notify the server about the new changes?
In our intranet, the network link between the client and the server is not particularly good so performance is critical.
It seems from my initial research that the common Silverlight architecture patterns call for as much of the business logic to be pushed back to the server. I understand the reasoning for this, but fear that it will really hurt the usability of our application.
Are there particular design patterns that address this issue? Is this 'client-binding' supported within MVVM, Prism or other common Silverlight architectures?
Is there a more formal name for what I am attempting to describe?
I am quite new to both Silverlight and design patterns such as MVVM, so please correct me if any of my assumptions are wrong.
The MVVM pattern is for separation of concerns. It does not define how or where you get your data.
The model, is data. It can be data you get from any arbitrary source. In silverlight, the most common way to get data is via a webservice (SOAP/REST). But your model can be any data from anywhere.
The view model is just another class that probably implements the INotifyPropertyChanged interface (So you bindings can automatically be updated). This class is an abstraction for your view's data. Let's pretend it has a string property called "FirstName".
The view is your UI (A user control in SL). You setup your bindings here to your ViewModel. IE, .
The view and view model are put together when you set your views DataContext. myView.DataContext = new MyViewModel(); There are many ways to set the DataContext depending how you want to set things up.
Prism is just a framework to help write decoupled applications in WPF/SL. It does not enforce the usage of any UI pattern (ie, MVP/MVC/MVVM). What it does come with is a bunch of classes can be used to assist with MVVM development, such as a mediator (EventAgggregator) and a dependency injection container (Unity).
So enough digressing...What I would suggest, is you have a web service where you can get all your data. You SL app would get that data (most likey the web services will be called in the view model). That data now exists on the client side and you can setup your VM to bind to this data in your view.