I have an MVVM application. In one of the ViewModels is the 'FindFilesCommand' which populates an ObservableCollection. I then implement a 'RemoveFilesCommand' in the same ViewModel. This command then brings up a window to get some more user input.
Where/what is the best way to do this whilst keeping with the MVVM paradigm? Somehow
doing:
new WhateverWindow( ).Show( )
in the ViewModel seems wrong.
Cheers,
Steve
I personally look at this scenario as one where the main window view model wants to surface a task for the end user to complete.
It should be responsible for creating the task, and initializing it. The view should be responsible for creating and showing the child window, and using the task as the newly instantiated window's view model.
The task can be canceled or committed. It raises a notification when it is completed.
The window uses the notification to close itself. The parent view model uses the notification to do additional work once the task has committed if there is followup work.
I believe this is as close to the natural/intuitive thing people do with their code-behind approach, but refactored to split the UI-independent concerns into a view model, without introducing additional conceptual overhead such as services etc.
I have an implementation of this for Silverlight. See http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx for more details... I'd love to hear comments/further suggestions on this.
In the Southridge realty example of Jaime Rodriguez and Karl Shifflet, they are creating the window in the viewmodel, more specifically in the execute part of a bound command:
protected void OnShowDetails ( object param )
{
// DetailsWindow window = new DetailsWindow();
ListingDetailsWindow window = new ListingDetailsWindow();
window.DataContext = new ListingDetailsViewModel ( param as Listing, this.CurrentProfile ) ;
ViewManager.Current.ShowWindow(window, true);
}
Here is the link:
http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx
I guess thats not of a big problem. After all, the Viewmodel acts as the 'glue' between the view and the business layer/data layer, so imho it's normal to be coupled to the View (UI)...
Onyx (http://www.codeplex.com/wpfonyx) will provide a fairly nice solution for this. As an example, look at the ICommonDialogProvider service, which can be used from a ViewModel like this:
ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>();
IOpenFileDialog openDialog = provider.CreateOpenFileDialog();
// configure the IOpenFileDialog here... removed for brevity
openDialog.ShowDialog();
This is very similar to using the concrete OpenFileDialog, but is fully testable. The amount of decoupling you really need would be an implementation detail for you. For instance, in your case you may want a service that entirely hides the fact that you are using a dialog. Something along the lines of:
public interface IRemoveFiles
{
string[] GetFilesToRemove();
}
IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>();
string[] files = removeFiles.GetFilesToRemove();
You then have to ensure the View has an implementation for the IRemoveFiles service, for which there's several options available to you.
Onyx isn't ready for release yet, but the code is fully working and usable at the very least as a reference point. I hope to release stabilize the V1 interface very shortly, and will release as soon as we have decent documentation and samples.
I have run into this issue with MVVM as well. My first thought is to try to find a way to not use the dialog. Using WPF it is a lot easier to come up with a slicker way to do things than with a dialog.
When that is not possible, the best option seems to be to have the ViewModel call a Shared class to get the info from the user. The ViewModel should be completely unaware that a dialog is being shown.
So, as a simple example, if you needed the user to confirm a deletion, the ViewModel could call DialogHelper.ConfirmDeletion(), which would return a boolean of whether the user said yes or no. The actual showing of the dialog would be done in the Helper class.
For more advanced dialogs, returning lots of data, the helper method should return an object with all the info from the dialog in it.
I agree it is not the smoothest fit with the rest of MVVM, but I haven't found any better examples yet.
I'd have to say, Services are the way to go here.
The service interface provides a way of returning the data. Then the actual implementation of that service can show a dialog or whatever to get the information needed in the interface.
That way to test this you can mock the service interface in your tests, and the ViewModel is none the wiser. As far as the ViewModel is concerned, it asked a service for some information and it received what it needed.
What we are doing is somethng like that, what is described here:
http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx
The ViewModel has a property that is called ConfirmDeletionViewModel. As soon as I set the Property the Behavior opens the dialog (modal or not) and uses the ConfirmDeletionViewModel. In addition I am passing a delegate that is executed when the user wants to close the dialog. This is basically a delegate that sets the ConfirmDeletionViewModel property to null.
For Dialogs of this sort. I define it as a nested class of the FindFilesCommand. If the basic dialog used among many commands I define it in a module accessible to those commands and have the command configure the dialog accordingly.
The command objects are enough to show how the dialog is interacting with the rest of the software. In my own software the Command objects reside in their own libraries so dialog are hidden from the rest of the system.
To do anything fancier is overkill in my opinion. In addition trying to keep it at the highest level often involving creating a lot of extra interfaces and registration methods. It is a lot of coding for little gain.
Like with any framework slavish devotion will lead you down some strange alleyways. You need to use judgment to see if there are other techniques to use when you get a bad code smell. Again in my opinion dialogs should be tightly bound and defined next to the command that use them. That way five years later I can come back to that section of the code and see everything that command is dealing with.
Again in the few instances that a dialog is useful to multiple commands I define it in a module common to all of them. However in my software maybe 1 out of 20 dialogs is like this. The main exception being the file open/save dialog. If a dialog is used by dozens of commands then I would go the full route of defining a interface, creating a form to implement that interface and registering that form.
If Localization for international use is important to your application you will need to make sure you account for that with this scheme as all the forms are not in one module.
Related
I am learning wpf. I am trying to utilize tdd practices with wpf. I have the following code in one of my viewmodels that saves data from a control into an xml file -
void saveStr()
{
string source = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\Data\Connections.xml";
DataGrid dg = FindChildViewItems.FindChild<DataGrid>(Application.Current.MainWindow, "MyDataGrid");
List<XmlSettings> list = new List<XmlSettings>();
foreach (var i in dg.Items)
{
if(i.GetType().ToString() == "MyProject.Configuration.XmlSettings")
{
list.Add((XmlSettings)i);
}
}
saveXml.Save(source, list);
}
The FindChildViewItems simply uses the visualtreehelper and dependency objects to find child items from the view (adapted from a post here).
My question is whether that adheres to tdd patterns since it has a dependency on the view when I am looking back to the view to get the contents of that particular control.
Is there another way to get the information from the datagrid on the view so that the contained data could be saved to an xml file.
I hope that makes sense......
Thanks for any thoughts.
Well, it looks like you're breaking several patterns here. It's definitely going to be very difficult to test.
Perhaps I can help you smooth out your structure a bit to make it more testable.
First, your viewmodel should not be saving state to a file! Your viewmodel should update the model whenever the user changes data in one of the datagrids, and nothing else. Use two-way databinding to allow your viewmodel to know when the view changes.
Persisting state to a file should be done in a different part of the program, possibly by a standalone command object, possibly in an event (alot of where this should occur depends on your program structure, and I can only guess at that). Regardless of where it occurs, it should be outside both your viewmodel and your model, and it should use your model to obtain the data it writes to a file.
After some minor tweaks to your method to account for this, it should be totally testable. Give it a stubbed model object (preferrably a class that only has user config settings) and let it go to town with your fake data.
Testing writing the file then becomes your biggest issue. Difficult to automate.
But testable.
Ideally, if you would like to do proper TDD (Test Driven Development), you should try to use MVVM Design Pattern. It separates View from the ViewModel, thus making the ViewModel and Model easily testable.
if you have used MVVM in the above example, your Model would have save() method in it and then you would call it from VM. That way you can easily test your Model to make it saves.
And later on you can also test your VM, to make sure when you call SaveCommand it calls your Model's method. let me know if you need further info (google for MVVM if you havent heard about it before)
I've been puzzled by this for a while. I am writing quite a large RibbonWindow WPF application using the MVVM pattern. The screen has a RibbonBar menu along the top and the rest of it displays the various Views. Some Views contain other Views and some of these have buttons that launch child Windows.
So far, I have been doing this from the View code behind file, but I'm aware that these files are supposed to be empty when using MVVM. I could move the child window launch code to the ViewModel, but then I would need a reference to the main RibbonWindow (to set as the child window owner) and that doesn't seem right.
Any advice or tips on how this is normally achieved using MVVM would be greatly appreciated.
I usually handle this by creating some sort of WindowViewLoaderService. When your program initializes you register your Window's and your ViewModels with code something like this:
WindowViewLoaderService.Register(TypeOf(MainWindowView), TypeOf(MainWindowViewModel));
WindowViewLoaderService.Register(TypeOf(MyWindowView), TypeOf(MyWindowViewModel));
Then when you can for example call into this service from your ViewModel and all you have to reference is your other ViewModel. For example if you are in your MainWindowViewModel you might have code like this:
var myChildWindowVM = new MyWindowViewModel();
WindowViewLoaderService.ShowWindow(myChildWindowVM);
The WindowViewLoaderService would then look up what View is associated with the specified ViewModel you passed it. It will create that View, Set its DataContext to the ViewModel you passed in, and then display the View.
This way your ViewModels never know about any Views.
You can roll your own one of these services pretty easily. All it needs to do is keep a Dictionary with the key being your ViewModelType and the value being your ViewType. The Register method adds to your dictionary and the ShowWindow method looks up the correct view based on the ViewModel passed in, creates the view, sets the DataContext, and then calls Show on it.
Most MVVM Frameworks provide something like this for you out of the box. For example Caliburn has a slick one that just uses naming convention its called ViewLocator in this Framework. Here is a link that summarizes: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/04/mvvm-study-segue-introducing-caliburn-micro.aspx
Cinch on the other hand calls it a WPFUIVisualizerService which you can see in action here:
http://www.codeproject.com/KB/WPF/CinchIII.aspx
These should help get you rolling.
Well, one remark to start with is that, "Having no code AT ALL in the code-behind" is actually a "myth". If you want to be pragmatic, and you see that having some code (as little as possible would be better), will make your life easier and solve your problem, then you should go with that.
However, in this situation, there are actually some loosely coupled ways to do this. You could have a service that does the interaction for you. You initiate the interaction with the user from the ViewModel, the service takes care of that (by showing a ChildWindow for example), and gives you back the user's reponse. That service can be mocked for testing easily. And it can be tested seperately.
That is, if you want to do things yourself. If you want a framework to do the heavy lifting for you, you can check out the InteractionRequest functionaity offered by Prism. Here's the MSDN article that talks about adanced MVVM scenarios which includes a section on User Interaction Patterns. That's the way I do it, and it's pretty simple, elegant and straightforward.
Hope this helps :)
To take Matt's answer one step further, you can have all your view's be a user control. Then create a ViewContainer, which is a window with your data templates (as you described).
Then you just ship the viewmodel you wish to open over to the window service, which sets the DataContext. The service would then open the window and the contentcontrol will resolve the correct view for the viewmodel.
This means all the registration is done in the XAML and the window service just knows how to do just that...open and close windows.
This is an old post, but maybe this'll help someone along the way: I use MVVM, and raise events for opening child windows from the ViewModel back to the View. The only code behind is handling the event, opening the window, setting owner of the child window and that's pretty much it. In the viewmodel, if the eventhandler is null, then it's not subscribed to by the view and doesn't fire. The VM does not know about the view. The code is pretty simple also and only takes a few lines.
In this situation View should handle the opening of the child windows.
However, ViewModel might drive the creation of the windows, but calling into View to create a new Windows.
This will save the logic of MVVM pattern: ViewModel has the "brains" but is not involved in a particular window creation.
ViewModel only is used to present system state and UI logic. One viewmodel may be referenced by multiple views. It have no knowledge of UI specific code like parent/child relationship, position, layout, size etc. So it is better to pop child window in view's code-behind with ViewModel's state changed event or command event and event arguments. In this way you can specify which one is the parent view in the UI layer.
I'm writing a WPF app following MVVM principles.
I wan't to execute a command on startup - I'm in doubt as to what is the best method?
The ViewModel should be indifferent as to whether there are any views, right?
Is it then 'ok' to do stuff as the last thing in VM constructor? Or is there an event for 'application is now up and running, all initialization has completed' that I can hook onto?
It feels wrong to wire it into the view model?
To be a bit concrete, I'd like to do as Visual Studio and load 'most recent solution' if the user has selected that in preferences. If the user manually loads a solution through GUI I start the flow in a MainFormViewModel and I could handle the load in last lines of constructor there?
Any thoughts?
Anders, Denmark
The Windows.Interactivity approach or asynchronously loading their preferences from the constructor are equally viable - an alternative exists if your using the MefedMVVM framework.
You can also import the IContainerStatus to attach to the view being loaded entirely from the view model (and therefore nothing to forget doing in the XAML) More info is available here
I really wanted to avoid calling methods from within the ViewModel constructor - and in my view activating events from constructor is doing just that (or at least when using Prism as I am (should have mentioned that).
I ended up doing the simple thing and simply calling a Loaded method on my main ViewModel after construction has ended.
Nonetheless, Scott singled out as the answerer - thank you all for taking the time. I appreciate your point of view even if I chose another way in the end.
Anders, Denmark
var mainViewProvider = ObjectFactory.GetInstance<IMainViewProvider>();
var mainWindowViewModelProvider = ObjectFactory.GetInstance<IMainWindowViewModelProvider>();
var mainWindow = mainViewProvider.GetView();
var mainWindowViewModel = mainWindowViewModelProvider.GetViewModel();
mainWindow.DataContext = mainWindowViewModel;
mainWindowViewModel.Loaded(Settings.Default.LoadLatestOnStart);
mainWindow.Show();
What you can do is use your MainForm's (the one which needs to load the solution) Loaded event.
Use Windows.Interactivity EventTrigger to attach a command to Loaded event. And on that command's execution, load the solution.
I would introduce Controllers which are responsible for the UI workflow. They know when the application has started and they can execute Commands. This doesn't violate with the MVVM pattern. If you are interested how this work then you might find the sample applications of the WPF Application Framework (WAF) interesting.
That's ok if and when you setup the context in code, but not if you do it from xaml - for the sake of transparency and flexibility one should consider supporting both code and xaml.
Another approach could be to trigger something on your model from xaml when certain criteria has been met.
I believe a storyboard could be used for this approach.
/Torben Falck, Strongminds, Denmark, www.strongminds.dk
I am starting my first foray into the world of Prism v4/MVVM with MEF & WPF. I have sucessfully built a shell and, using MEF, I am able to discover and initialise modules. I am however unsure as to the correct way to provide navigation to the views exposed by these modules.
For example, let's say that one of the modules exposes three views and I want to display navigation to these views on a menu control. So far, I have sucessfully exposed a view based upon a MenuItem and this MenuItem contains child MenuItem controls thus providing a command heirarchy that can be used. Great.
Thing is, this feels wrong. I am now stating within my module that navigation (and therefore the shell) MUST support the use of menu's. What if I wanted to change to using a ToolBar or even a Ribbon. I would then have to change all of my modules to expose the corresponding control types for the shell.
I have looked around and there is mention on some sites of using a "Service" to provide navigation, whereby during the initialisation of the module, navigation options are added to the service which in turn is used by the shell to display this navigation in whatever format it wants (ToolBar, TreeView, Ribbon, MenuItem etc.) - but I cannot find any examples of actually doing this.
To put all of this into perspective, I am eventually looking to be able to select views from a menu and/or other navigation control (probably a Ribbon) and then open those views on demand within a TabControl. I have already gotten as far as being able to create the views in the TabControl at module initialisation time, now I need the next step.
What I need to know is this: what would be the correct way to expose navigation options in such a way as not the insist on support of a specific control by the shell, and if a service is the way to go then how would one put this together within the Prism/MVVM patterns.
Thanks in advance for any insight you can offer.
I suppose you have a main module containing common interfaces.
You could create a simple interface like
public interface IMenuService {
void AddItem(string name, Action action);
IEnumerable<MenuItemViewModel> GetItems { get; }
}
Create 1 implementation and a single instance.
public class MenuService : IMenuService {
private readonly IList<MenuItemViewModel> items = new List<MenuItemViewModel>();
void AddItem(string name, Action action) {
items.Add(new MenuItemViewModel {
Name = name,
Action = action
});
}
IEnumerable<MenuItemViewModel> GetItems {
get { return list.AsEnumerable(); }
}
}
Within your modules, use MEF to resolve this instance and call AddItem() to register your views.
The Action property is a simple delegate to activate a view or do anything else.
Then in your shell or any view, you just need to call the GetItems property to populate your menu.
Having thought about this some more, I have come to the following conclusion that I feel affects the way that I need to deal with this...
The modules need to be partially aware of the shell layout anyway - that is, the shell exposes a number of regions and the modules need to be aware of those regions (by name as well as what is expected to be shown) in order to populate them correctly when functionality is requested (either by means of registering a view within a region or as the reaction to a user action).
Because of this, the modules need to be designed to interact with the shell to place content into the named regions and as such, I see no reason why the modules should not expose whatever type of navigation the shell supports.
Therefore, my modules (currently) expose a "RibbonView" (a RibbonTab) with the necessary icons, buttons and commands etc to expose the functionality of the module. Each "RibbonView" is registered with the "RibbonRegion" of the shell, along with hints for ordering, and this is then rendered within the shell.
If in the future I choose to update my shell to use the latest+greatest navigation control (whatever that may be in x years time) then I simply need to update each of the modules to expose the necessary items to integrate with that new navigation and, because I am loading into a new shell, I can then update my view registration accordingly.
I just hope that I am not breaking any of the principles of the composite application in doing this, but that said I have never yet found a pattern that can actually be implemented in a real scenario without some "interpretation".
I would be interested to hear if anybody has any opinions on this.
I've encountered the same situation, and I think the solution lies in differentiating between interface and implementation. For example, you can design a view in a module that performs a given function. That's all it does. As soon as you use or consume this in a specific context you've crossed over into implementation. Now, ideally the view is unaware of how it's being implemented, and certainly would have no knowledge of named Regions in the Shell. So, seating views into Regions within a module is a no-no.
To get around this, I've opted to delegate this responsibility to a third-party component, a LayoutManager. The LayoutManager sits between the Shell and Module and defines "what goes where". It is a specific implementation, and really defines the implementation. Both the Shell and the Module view remain generic.
Have a look at: http://rgramann.blogspot.com/2009/08/layout-manager-for-prism-v2.html
Which may give you some ideas around this problem.
Hope it helps.
This article uses an abstraction (IMenuItem) to represent the ViewModels for your menu choices. How you actually render these imported objects is really up to the host application. The example uses a WPF menu, but you could certainly render it any way you wanted because IMenuItem is abstract enough.
If you changed IMenuItem to INavigationItem, you've got what you want.
In that article, when the particular navigation item gets notified that it's been "run", then it usually instantiates a ViewModel for a document or "pad", and passes that to the ILayoutManager service. It has a pluggable architecture, so you can swap out the LayoutManager service for a different layout engine (the default one is a wrapper around AvalonDock).
I have an application that need to open a dialog from a button where the user enters some information.
At the moment I do it like this (which works fine)
The button click generates a command in the ViewModel.
The ViewModel raises an event which the Controller listens to.
The Controller works out the details of the new window (i.e. View, ViewModel & model) and opens it (ShowDialog)
When the window is closed the Controller adds the result to the eventargs and returns to the ViewModel
The ViewModel passes the information to the Model.
There are a lot of steps but they all make sense and there is not much typing.
The code looks like this (the window asks for the user's name)
ViewModel:
AskUserNameCommand = DelegateCommand(AskUserNameExecute);
...
public event EventHandler<AskUserEventArgs> AskUserName;
void AskUserNameExecute(object arg) {
var e = new AskUserNameEventArgs();
AskUserName(this, e);
mModel.SetUserName(e.UserName);
}
Controller:
mViewModel.AskUserName += (sender,e) => {
var view = container.Resolve<IAskUserNameView>();
var model = container.Resolve<IAskUserNameModel>();
var viewmodel = container.Resolve<IAskUserNameViewModel>(view, model);
if (dlg.ShowDialog() ?? false)
e.UserName = model.UserName;
}
My question is how the horizontal communication works in the MVVM pattern.
Somehow it seems wrong to let the controller be involved in the data transfer between the models.
I have looked at the mediator pattern to let the models communicate directly. Don't like that idea since it makes the model depending on implemetations details of the GUI. (i.e. if the dialog is replaced with a textbox, the model need to change)
I don't like most of the current suggestions for one reason or another, so I thought I would link to a nearly identical question with answers I do like:
Open File Dialog MVVM
Specifically the answer by Cameron MacFarland is exactly what I do. A service provided via an interface to provide IO and/or user interaction is the way to go here, for the following reasons:
It is testable
It abstracts away the implementation of any dialogs so that your strategy for handling these types of things can be changed without affecting constituent code
Does not rely on any communication patterns. A lot of suggestions you see out there rely on a mediator, like the Event Aggregator. These solutions rely on implementing two-way communication with partners on the other side of the mediator, which is both hard to implement and a very loose contract.
ViewModels remain autonomous. I, like you, don't feel right given communication between the controller and the ViewModel. The ViewModel should remain autonomous if for no other reason that this eases testability.
Hope this helps.
i use this approach for dialogs with mvvm.
all i have do do now is call the following from my viewmodel to work with a dialog.
var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
I have come across similar problems. Here is how I have solved them, and why I have done what I have done.
My solution:
My MainWindowViewModel has a property of type ModalViewModelBase called Modal.
If my code needs a certain view to be modal, it puts a reference to it in this property. The MainWindowView watches this property through the INotifyPropertyChanged mechanism. If Modal is set to some VM, the MainWindowView class will take the VM and put it in a ModalView window where the appropriate UserControl will be shown through the magic of DataTemplates, the window is shown using ShowDialog. ModalViewModelBase has a property for DialogResult and a property called IsFinished. When IsFinished is set to true by the modal VM, the view closes.
I also have some special tricks for doing interactive things like this from backgroundworker threads that want to ask the user for input.
My reasoning:
The principle of modal views is that other views are disabled, while the modal is shown. This is a part of the logic of the View that is essentially lookless. That's why I have a property for it in the MainWindowViewModel. It I were to take it further, I should make every other property or command for all other VM's in the Main VM throw exceptions, while in modal mode, but I feel this to be excessive.
The View mechanism of actually denying the user any other actions, does not have to be performed with a popup window and showdialog, it could be that you put the modal view in the existing window, but disable all others, or some other thing. This view-related logic belongs in the view itself. (That a typical designer can't code for this logic, seems a secondary concern. We all need help some times.)
So that's how I have done it. I offer it only as a suggestion, there is probably other ways of thinking about it, and I hope you get more replies too.
I've used EventAggregator from Prism v2 in similar scenarios. Good thing about prims is that, you don't have to use entire framework in your MVVM application. You can extract EventAggregator functionality and use it along with your current setup.
You might have a look at this MVVM article. It describes how a controller can communicate with the ViewModel:
http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&ProjectName=waf