I'm using AvalonDock in a WPF application, and need to persist the layout of the AvalonDock the user has setup (moving, docking, detaching of the panels).
The function to do that are on the control itself (SaveLayout, RestoreLayout).
What is the correct way to do that ?
Right now I have a command at the mainWindowViewModel that gets created by the application when creating the instance of the window view and the viewmodel. It basically makes the relay command call an anonymous method that calls the needed function on the view control. This works since the application creates the window and the viewmodel for it.
But how would i approach this if some lower level view and viewmodel had to do this? If using this method I'd have to still create the Command at application level and sending it through the viewModels down to where it is needed to be bound to? Inside it I'd have to search the usercontrol that is a view then the avalonDock control inside it and use that at application level, which is bug prone. Somehow it seems dirty...
Thanks!
You might introduce an interface IView so that the ViewModel can call a method on the View. This way the ViewModel doesn’t need to know about the concrete View class and can still be unit tested.
How this can be accomplished is shown by the sample applications of the WPF Application Framework (WAF).
You can use decoupled messaging to communicate between view models
http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html
Related
I am building an app using UWP and I have MainPage.cs which contains a Frame control where I load different child pages. I would like to pass a listener to the child page to notify my parent page about event that happen in the child. On android I would pass a callback listener which I will have to trigger in the sub-pages so I can get notified in parentl The issue here is that pages are started Frame.Navigate(typeOf(LoginPage)) for which I cannot set a callback since login page is not a referece/object but a type class.
Any help would be greatly appreciated.
It seems like the MainPage is a singleton instance. In such case you could just expose this instance by creating a static MainPage Instance property in MainPage and set it in its constructor. Then you could access MainPage directly from any other page.
The proper solution however would be to use a MVVM framework and instead of communicating between the views directly put the communication within the view models. In MVVM you usually have a sort of navigation service which allows passing parameters/return values and also you can have a event aggregator to raise messages to which other components can subscribe. Good examples of MVVM frameworks are MvvmCross, MvvmLight and Prism. It is definitely worth learning to use and integrate them early on, because it will make your life significantly easier in terms of code maintenance in the long run.
I have to convert a decent sized Winforms application into a WPF app following the MVVM pattern. I'm not sure what the best way to do this is.
The application is built around a third party map control.
Multiple windows: A main window that displays the map, and other windows that allow the user to change properties of the map (add layers, change styles, etc).
My plan was to create a viewmodel for each window, and have a base viewmodel containing the map control itself and any properties/methods that needed to be shared.
The main thing I'm not sure about is how to handle the map operations that are built into the control. For instance, there is a MapMouse_Down event. Normally I would just put this in the code behind if I wasn't following MVVM, and handle it there. Is that the correct way to handle this?
Normally I would just put this in the code behind if I wasn't following MVVM, and handle it there. Is that the correct way to handle this?
You could keep anything that is purely view related in the code-behind of the views but anything that is testable application logic should be implemented in view models. View-related stuff may for example be animations and any code that changes the behaviour or appearance of a control in some way, like for example setting some width or colour.
There are different ways to handle "events" in MVVM depending on what kind of controls you are using but you would generally defined commands in the view model and invoked these from the view. Please refer to this blog post for more information.
Having a separate view model for each different type of window is ideal.
View models should never contain controls. They should contain only abstractions of the controls. If all of your windows have mapping components, only then should your base window view model have an abstraction of the mapping control. (An example of the sort of abstraction I'm talking about: Imagine a view that where the user should enter a name. The view will have a TextBox which has a Text property. The view model will have a Name property. The view will bind the TextBox's Text property to the view model's Name property. Figuring out the right abstractions for larger applications is one of the challenges of MVVM.)
It's perfectly fine to have event handlers in your view if your controls don't support data binding or they don't have ICommand support. But the event handler in your view should do as little as possible, instead just transferring control over to your view model, which will update its abstract representation of the view, which the view will then re-synchronize to through data bindings or manual synchronization logic.
WPF is different for Winforms, the approach is based on the binding of proprety .
Below an Example of using MVVM.
Easy MVVM Example
I am developing a view-based application using the MVVM-Light framework (C#). Essentially, I have a single window that opens with a content controller, and the view models determine which view is in the content controller.
I would like to run commands from each individual view model that changes the view. For instance, if the user were to press "Submit", the application would take them back to the main view.
The only thing I can think of is to have each view model require a ParentWindow argument of type Window in order to link back to the CurrentViewModel variable in my MainWindowViewModel. Is there a better way to do this?
In MVVM Light there is a feature called Messenger. You could use this to communicate between ViewModels.
Here is an answer with an example of that: MVVM Light Messenger - Sending and Registering Objects
I have a plugin based application where I am discovering plugins using Mono.Addin. Each plugin has its own View and ViewModel and I am not sure the best method to pass the View down to the MainView. At the moment my MainView is binding to an object type on my MainViewModel, but this requires me to have UI specific logic in my plugin ViewModel. I am not entirely comfortable doing this but cant think of a better way.
My MainViewModel has this
public object Content
and my PluginViewModel does this
this.MainViewModel.Content = ViewLocator.Current.ResolveView(this);
If you're using MVVM then the usual way of creating a view from a view model is via data templating, and in order for that to work both the view and data template need to be merged into the application's global ResourceDirectory. There's another answer here that shows to do that with the MEF plugin architecture but it shouldn't be too difficult to adapt to others.
I'm trying to create a strategy for handling popup forms for use throughout any part of my application. My understanding so far is that I will need a single UserControl in the root of my MainWindow. This will be bound to its own ViewModel which will handle the messages that are sent within the app.
I'm using MVVM Light, and I'm fairly new to the Messenger class.
Imagine a Master/Details scenario, where a list a objects are contained within a ListBox. Selecting one of these items and clicking an Edit button would display a UserControl which covers the whole screen. The user can then edit the selected item, and click OK to commit the change.
I want the UserControl that is opened to be "generic" in a way that I can throw any (probably a ViewModel) at it... for it to render the ViewModel via a DataTemplate and handle all the object changes. Clicking OK will callback to the sending class and persist the change as before.
Some situations where this would be useful are...
Display error messages with no required user input (other than OK to close it)
Display an edit form for a data item
Confirmation dialogs (much like a standard MessageBox)
Can anyone provide any code samples of how I might acheive this?
When designing a UI with MVVM the goal is to separate the concerns of the View from the concerns of the ViewModel. Ideally, the ViewModel should not rely on any view components. However, this is the idal and another rule of MVVM is that you should design your application as you wish.
In the area providing a service showing dialogs there are two different approaches floating arround:
Implementing the DialogService on the View (e.g. see http://geekswithblogs.net/lbugnion/archive/2011/04/13/deep-dive-mvvm-samples-mix11-deepdivemvvm.aspx Sample 03).
Implementing a service component that does is not attached to the view (e.g. see http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/)
Both approaches rely on an interface that defines the functionality the service provides. The implementation for this Service is then injected into the ViewModel.
Also, do both approaches have their specific advantages and disadvantages.
The first approach works also well for WP7, however, it requires a common view base class as this contains the implementation of the view service.
The second approach works well for SilverLight and WPF and appleals as it keeps the service separate from the view and does not impose any restictions on the view.
Another possible solution is to use messaging to show the dialogs.
Whatever approach you are using try to keep the View and the ViewModel de-coupled by using an IoC (inversion of control) pattern, i.e. define an interface so that you can use different implementations. To bind the services into the ViewModel use injection, i.e. passing the service into the constructor of the ViewModel or by setting a property.
I recently started learning MVVM for a WPF app I was creating, I used this article as a basis for showing dialogs, if you download the sample project then it is actually quite a nice decoupled method, it is nicely abstracted and to get a view you pass an instance of a viewmodel. I extended it somewhat for my own means, I also used the WPFExtendedToolkit MessageBox for warnings, errors etc because the standard win32 MessageBox is fugly.
With regards to dynamic forms then you'll want to investigate the ItemsControl, and in your ViewModels have a Collection of Data Items which need to be edited by the user for the ItemsControl to bind to. I have a dialog for editing actions and their parameters in a workflow system designer where the dialog list of actions was totally dynamic. This was done by exposing a collection of my items with their data types so I could then use a DataTemplateSelector to select DataTemplates which contained the correct types of controls, i.e. a datatype of DateTime showed a DatePicker.
Hope That Helps
From the perspective of a developer coming in to 'maintain' that generic code, it sounds like a pain. From what you've described, I would give the form and the dialog the same view model and create a specific XAML template for the dialog that you want to show.