MVVM design Question - wpf

I have an application with two forms ( windows )
They represent the front and back of an ID card
Users enter data and the printer spits out something that can be folded and laminated to give the front back effect
I am using different Views to show the front and back and I guess my question is how do I use the same ViewModel instance in both( the data needs to be saved to a DB before printing )
Or am I doing this all wrong and I should just have one view and show hide Front\Back ( i really hate that )
Thanks

Generally, you are going to want one ViewModel per View, since the job of the ViewModel is to provide exactly the data needed by the View it is attached to.
So, in your case, it sounds like you should have one View and ViewModel for the front and one View and ViewModel for the back.
There are several ways you could go about saving the data when the user submits the form. A common pattern is to set up Repository classes for each of your database tables. Repository classes typically allow you to select, insert, update, and delete data. So, you could pass the necessary Repositories into each ViewModel, then when the user submits, have the ViewModel tell the repository to insert or update the data.

Related

Reusing WPF MVVM Views

I've inherited an application which uses the view-first MVVMC patern
In the application I've created 2 step process which creates a person and assigns them to a group. To do this I've created a view and corresponding view model (all views have a 1-2-1 relationship with a view model, view models are injected into the View constructor and are registered with the Unity container using the TransientLifetimeManager) called CreatePersonMaster, the view simply contains a region (shown by the dashed line) which sub-views can be loaded into and the view model subscribes to two loosely coupled events, "PersonCreated" and "GroupSelected". The "PersonCreated" event saves a Person entity in a field and the "GroupSelected" event takes the saved Person, creates a Group association and saves them to a database.
This view/view model doesn't do anything until the events get raised so I load the following sub views into my the region.
These views/view models fire the events which get handled by the master view.
I also have an edit view where I want to re-use the select group view.
I can do this by subscribing to the appropriate events in the EditPersonMaster view model.
My question really is, is this the appropriate way to do this? Because I'm using loosely coupled events I don't get any feedback into the sub-View/ViewModels if there's an error when creating/reassigning? I could probably fire another "ErrorBlah" event for the inner view/model to handle and update the view.
Is there another way to do this? Composite commands don't seem to fit the bill but maybe I don't understand them correctly.
Here is how I understood your question: You have persons stored in a database, which have a property/column group. In your UI, you want to create persons and assign the group property. Also, you want to be able to edit the group property of existing persons in a different region/page/master. You want to reuse the control for assigning the group. Your controls fire an event, which is handled by the Master in a way that it creates the entries in the database (is that correct?). Your question is whether this is a good approach and what alternatives you have?
I see two options:
1. Modularize your business logic:
You could inject a data service into your ViewModels, which could access the database directly. This way you can handle errors etc.. directly where they occur and don't have to pass them through the whole system. If you want to notify other modules of changes on the database (specifying the changed dataset or so), you can do so with a composite event. I think of the PRISM modules more as of complete elements, including UI and business logic and keep communication between them as little as possible.
2. Keep your business logic central and share it:
If you want to stick to your architecture, have singleton Model which is injected into the ViewModels. Manage your state in the model and have the ViewModels pick the pieces they want to provide to their view.
Hope I got he point, though...

Prism - strategy for removing newly added record from master view

I have a typical master-detail scenario. User can click "Add New" in the master view and enter the details in the detail view. So for example lets say I have list of ObservableCollection of Product. When the user clicks "Add New", I add a new Product record to the ObservableCollection and then open a detail view for adding the Product details. This works well if the user does save the product. However if the user decides to cancel the addition of new Product, how do I remove the same from the ObservableCollection of Product in the master view. Right now I could think of two ways, first to pass the reference of ObservableCollection to the Details view, and second, use events to notify master view about the new Product record deletion. What do you suggest ? Also, if there is better way to handle this in prism specifically, please let me know.
regards,
Nirvan.
Passing a reference to the ObservableCollection to the details view is a no-no - it should only know about the record it is bound to.
You have not specified the UI you have in place for this, there can be a couple of ways to do this that may be better suited for your design. However one reasonably agnostic way to do it is to use the EventAggregator to publish the event which the master view can subscribe to. It is up to the master view how to deal with that event, different views can respond in different ways. In this particular case the master view can check the currently selected item, and if it is new (i.e. hasn't been saved, doesn't have key pieces of info like an ID) then it can simply remove it from the collection and discard it.

MVVM Multiple Edit Windows

Please am still new to MVVM, and am using it with Sivlerlight. I run into a scenario where I have a Main UserControl containing one DataGrid, Employees forexample. User can double click any datagrid record to Show the EditEmployeeWindow (non blocking) so users can at the same time edit more than one employee. The only problem I have is that (one of our requirements) that when the users click save on any Edit,New window the data has to be saved to the database directly, and with one model a Save operation will save all the changes.
So one of the solutions on my head is to create an EditorViewModel that has it's own Model (new Instance of the model) and take id of edited record. In the EditorViewModel I will load this single record freshly and would direclty save changes only to that record. Also to use MVVM-Light Messenger to send message to the MainViewModel to refresh it's data since it they'll not be the same anymore.
Please could you guide me! Am I on the right track?
Thanks in advance
It looks OK, but I strongly recommend you to store the list of editing records somewhere in the main view model to not allow multiple windows on same record. Also, as you already going to use messenger to communicate with main view model, when main v.m. will receive it's child window closed message, send message to other windows, forcing them to close, and then call refresh method on main v.m.
It actually may be a little bit tricky to identify when all windows are closed (as you do work async), there are a lot of ways to do this, but I recommend you following:
1) Track a state of the main view model (is it has opened window, waiting for all windows to close, etc)
2) When window commit operation finished notify main v.m. and remove id form the list of active records.
3) When there no more records left in the list, refresh data.
Eventually when you will have to add more logic related to popup windows, I recommend to extract popup related code to the class named something like PopupService, it should be singleton, but I strongly recommend you to get it instance through one of the IoC containers (Unity, MvvmLight one, or event MEF).

Which is proper way to create PresentationModel in Silverlight RIA Service?

I have search employee page and edit employee date. User can search data in employee search page and it will show first name and last name of employee, so I create SearchEmployeeEntity in my presentation model. When user click edit employee, I will get data from service, this time I get first name, last name, username, birthday and other informations, so I create another presentation model name EmployeeEntity.
I think about my design for a while, there are two way to doing this, one is as I just explain above, other is use only one presentation model (EmployeeEntity) in both service.
Anyway, if I use EmployeeEntry in all place (search page and edit page) it's quite hard to manage data since I use static DomainContext.
Please suggest me, which way is good to create presentation model in Silverlight Application?
P.S. I use MVVM at my client.
It's the same entity so you should only need one. What's different is the context in which it is used - either you're creating a new Employee, or editing an existing one.
Silverlight RIA Services will handle this for you as it knows how to perform change tracking.
So, when you are editing, you will do a lookup against your context and perform a LoadOperation, which will return the entity to you from the DB. Allow the user to edit fields of the Employee on the clients ide, and then perform a SubmitOperation to persist the changes to the DB.
For new Employees, you create a new EmployeeEntity in your ViewModel, and then add it to the Context's Employees collection. Like so:
EmployeeContext.Employees.Add(Employee);
When the fields are filled out correctly (and hopefully you're taking advantage of Silverlight's super-easy validation rules to ensure correct data) then you, again, perform a SubmitOperation to save the new entity to the DB.

MVVM WPF ViewModels for Adding New Entity

My concept for MVVM in WPF is that we have a ViewModel for every Model in your application. This means that if we have Customer class (entity) then we will have CustomerViewModel. The CustomerViewModel will have all the properties which are necessary to represent a customer. The CustomerView usercontrol will be responsible for creating the UI for the Customer model.
Now, let's say that we are adding a new customer. So, we have a form which consists of FirstName, LastName etc. Do we need a ViewModel for this scenario. I mean all I have to do is to take all the input values from TextBox and create a Customer object and then save it to the database. Why should I bother creating a ViewModel for this scenario?
First of all, that is not the main purpose of MVVM, to "mirror" everything. The View should provide the means for a user input, and certainly not process calls to any of the database layers. The ViewModel should be a GUI-agnostic application backbone, and it definetly should handle the creating of customers.
That said, what you should do, is have a ViewModel which represents a workspace for handling customers, and not just a customer ViewModel. If you really want to save on a few objects being created, add to that workspace the possibility to create and add a new customer (not CustomerViewModel). That way, you can have a View of the workspace which has elements for each relevant/required property of the customer, and by invoking some command added to that workspace ViewModel, you could get the current values filled in those (data bound to ViewModel) View elements directly to the customer model.
Consider if you could probably drop the specific customer (and other Model) ViewModels if you refactor things a bit, it would be good practice to keep things from adhering blindly to a certain pattern without explicit cause.
Let's pretend for a second that there is no business model. The only thing you have is a view. If you were to model just that view, without any knowledge of what the data means elsewhere in the system, that is a ViewModel.
The goal of a ViewModel is to, well, model the view it backs. This is a different goal than modeling the idea of a customer in your business domain. To say you will have have one ViewModel per business entity, then, is to say you will have one view per business entity, which leads to run-of-the-mill data-focused UI.
In your particular case, think about the customer edit view. It has fields that correspond to a customer's properties, and thus seems like a natural fit for binding to a customer directly. However, where on the customer object is the "Submit" action modeled? Where is the "Cancel" action modeled? Where is it modeled that field X is an enumerated value selected from a list?
How about the password? If persisted as a binary hashed value, does the view know how to hash its text? What if the system has password strength requirements?
The ViewModel is the mortar between the business model and the UI. It takes concerns from one and translates them into terms of the other. It is the point at which all the above issues are addressed. To say a ViewModel isn't necessary is to ignore its necessity.
You don't need to have a separate ViewModel for Add, you only need a single ViewModel which should do Edit and Add scenarios. If you can delete the record from the edit page than that ViewModel should also have the ability to delete. Your ViewModel should reflect the functionality your View exposes regardless of data.
I think you should reconsider having a single ViewModel for each model. I like to think of ViewModels as normalizing behavior inserted of data. By having a ViewModel for each Model class you will run into architecture issues sooner or later. I look at the application from top down overview, what is my UI trying to accomplish and from there I will get to the ViewModel and eventually I will get to my DataFactory and how the ViewModel maps down to data is almost always not 1 to 1 except for the most simplistic Views. If you try to map 1 to 1 you will have bad UI or your data will not be normalized very well.
The Stack we have here is:
View
ViewModel (Controls everything the user can do in the view, wraps properties from our POCO's)
DataFactory (Maps our POCO's to Entity Framework objects and CRUD)
POCO's (Business Logic, all rules and validation)
Entity Framework (Model, Data Access)
One note here is that ViewModel contains properties from multiple POCO's!
We inject the DataFactory through StructureMap and Unit test with xUnit along with Moq.
To answer you second question I would create a separate view only view to drop in as a user control. But you should still have a CRUD ViewModel in you app that encapsulate all that functionality in a user friendly way.
Thanks.
One reason for this VM abstraction is for testability. Another reason why you want a ViewModel is because it's basically a Data Transfer Object that might be a combination of fields from multiple models in a single container that is more relevant to your current view. Yet another reason to have VM is to take advantage of WPF two ways binding capabilities.
Using your regular model (plain POCO), you can update the View when your model change, but since your model does not implement dependency properties (most likely), you won't be able to take advantage of updating your model when the value in WPF control changes. Which mean you have to manual add a handler and do the copy this value from this control back to the model kind of thing.

Resources