MVVM Multiple Edit Windows - silverlight

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).

Related

MVVM without 'standard model'

Almost every tutorial explains MVVM in WPF in the same manner: We have some entity (Person, Student, Car etc) - we create a Model class for it that will only carry data (it might also implement INotifyPropertyChange, IDataErrorInfo and whatnot - doesn't matter now), then we create a View-Model for that class, that will query and/or save our entity/ies somewhere (most likely via Commands) - our View will bind to the View-Model and voilĂ .
Let's say we have an application that won't, for a difference, work with querying/saving entities. Let's say it should contain a button that when clicked will download an .exe file (in a background thread) and will launch it. I'm curious, how would you approach this (architecture-wise) - would you actually create a folder/class named 'Model' for that program? What would it contain? How I see it, I'd have two abstractions - one for downloading a file and one for launching it. I'd inject them to View-Model and call their methods (via Command) and that's it. Or should it be a Model class that contains these abstractions? I know this question might seem strange, but it's something that's been bothering me for some time.
Btw, I realise the title of this post doesn't tell much - I didn't have a better idea for it, if someone does - feel free to change it.
For the example you provide, how the MVVM model will be setup is as follows. Let us assume that you want to download some data and show it in a DataGrid which is part of your view. In the View you add your DataGrid and Button, bind your button click to the ViewModel via a command. Bind your DataGrid via ItemSource to some ObservableCollection<T> in the view model (the view model must implement INotifyPropertyChange). Now, when the user clicks the button the command will fire and you can go and fill you ObservableCollection<T> with data via the download, the downloaded data which is bound to the UI will automatically display...
I hope this helps.

Load view on double-click of row - have bindings working, and event being fired on click, but how do I actually get the view to pop up?

I have a view in Silverlight which contains a telerik:RadGridView with a number of columns.
I have it wired up so that when the user double-clicks on one of these columns, an event is fired. However, I don't know what to put in the event handler.
private void RowClicked()
{
//What goes here?
}
All I wish to do is load a popup view over my current view, with a close button so that the user can return to the previous view. A simple idea that is surely done a billion times everywhere, but I cannot figure it out or find examples of this anywhere.
Can anyone help?
Thanks very much.
You can set a previous view as input parameter to "RowClicked()" method. You will have a reference on previous view in current method. You can use it via Commands (bind a command and a command parameter to some action/event).
I have an one more idea (if you have a lot of views): you can create a navigation service. It is an interface, which contains events and methods. You should use events for navigation and methods - for sending needed data. Everyone of view should implement this interface. Needed event will be raised under view via some action (for example: button click). As for events: you can create a custom event handler, there you will set a sender instance and needed parameters. You should create a Navigation manager, there you should create a property for selected view and subscribe on everyone event. If user want navigate to another view, he will do some action and system will raise an event. You can create a custom container for created views. This container you can use for getting created instance of needed view. As you know, creating a new instance is heavy for system: need a some time and system resources. Will be easy to get a created instance of view instead a create a new. For setting default data or refreshing a binding you can user a custom method, contractor for which will be added to navigation interface.
It is a simple idea, which I used in one project. As for others samples: You can find another navigation frameworks and custom classes in internet. But, process of creating an own system will give you a level up in your work experience.

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 design Question

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.

Managing silverlight RIA services context lifetime

I'm working on a line-of-business silverlight application and I need a piece of advice concerning managing RIA services context lifetime.
Application - afer a few simplifications - is build of one big tab control. At the beginning there are 2 tabs: customer list and invoice list. These are plain datagrids with filtering/sorting and that sort of stuff.
User can add/edit customer or invoice selecting a row and double-clicking. Then the new tab is created with details of customer or invoice. User can open many tabs with different customers/invoices. After editing, user can save and close tab or just abandon edit and close.
The question is how to deal with data contexts.
Should I create one for customerlist and one for invoicelist and when user opens a new tab, I simply bind customer/invoive dataobject to control? This has an advantage that I dont need to refresh grids after saving changes. EDIT: This has some drawbacks. User can refresh grid - and what will happen to open detail tabs? User can also filter grid so some records being edited can be removed from datactx?
The other way is to create datacontext per tabitem. This is more safe but I need to handle refreshing grid(s).
I have no idea which method is better or maybe there is another alternative?
Use one ObservableCollection list in each case and it will automatically update the datagrids when items are changed.

Resources