I have a WinForm based solution, being implemented using MVP.
We have Menus which should use a Command per Menu and there are other mechanism to invoke commands as well.
Now.. from a concrete implementation of the View, view elements (menus, buttons etc) are bound to Commands using a CommandBinder.
My question here is How should Presenter be linked to Commands?
Should each command call Presenter's respective function?
Should each Presenter own the commands and be called from there?
Related
I have a WPF/prism application similar to the mockup shown below:
Both TabControls contain a separate Prism region, the second one being nested into the first one. Now the toolbar should activate/deactive items depending on which view is currently active.
The toolbar is currently defined in the shell.
I tried using some sort of registry, where each ViewModel could register the toolbar commands it supports. However I then realized that the toolbar cannot know which view (and therefore which viewmodel) is active.
The problem is in the nesting, without that I could probably achieve what I wanted by binding the TabControl.SelectedItem property to the toolbar and use my registry from above.
Maybe there is a better way to do this? Or a way to let the toolbar find out which view is active?
edit: I now tried to use ActiveAware ViewModels as descriped in this article: http://www.codeproject.com/Articles/56826/ViewModel-Active-Awareness-in-a-Prism-Based-Applic, however I now have the problem that when I switch from Tab "One" to Tab "Two" and back, the nested tab's "First Tab" GotFocus event is not fired, meaning the toolbar will represent the wrong view.
Maybe this is the way to go?
edit 2: The problem seems to be that the second tabcontrol is not inside it's own scoped region. I'm using the ViewDiscovery approach to add views to my regions, so I'm not explicity creating the regionmanager in a scope. SyncActiveState seems to work only with scoped regions, as the first tabcontrol viewmodels correctly get updated when switching views.
Is there a way to use XAML to create a scoped region instead of a normal one?
The problem here is that the toolbar does not know anything about the active region; they are deliberately decoupled.
I would (personally) use the Event Aggregator to publish messages from the active ViewModel to say "I am currently active" and have the toolbar subscribe to those messages and update the buttons as appropriate.
If I were attempting to do this, I would probably create an IToolbarManager which has bool properties for each of the available toolbar actions, and an ICommand for the actions themselves.
Then, implement this interface in a concrete type where the bool properties change the CanExecute values of the commands, and call CommandManager.InvalidRequerySuggested. Register this type as a singleton with the container, then use DI to inject it into each of the views and into the shell. The Shell can then databind the Toolbar buttons to the Commands in the IToolbarManager, and the views can then set whether or not the actions are enabled as they get initialized.
I don't have a code sample because I'm just thinking through how I'd solve this, but hopefully you can follow what I'm suggesting, and it proves helpful.
I now ended up with creating an extended TabControl that uses the SelectionChanged event to set IsActive on all items implementing a specific interface. Also it walks down the VisualTree and finds any extended TabControl and does the same for the items of these and so on.
Work pretty well here, we only use TabControls so far, so this solution works for me.
I have few Views that represent the same data in different ways (Grid, TextBox, etc..) and in different locations in application.
Every view is bindded to different View-Model.
I have a commands like Add-New, Update, Delete, etc... on the selected row/s. The commands can execute on the active View from a main toolbar (different view), a button on that view, right click menu and some other place.
I don't want to rewrite the commands for every scenario that the command can appear.
Is there any other way to preform it without duplicate the code of the commands and without a massive switch for every scenario.
Thank you.
You can either use the CommandBindings which holds commands in one main place (window for example)
and the call it from each view or control under its scope.
Or create a "CommnadViewModel" which each specific viewModel would get on its constructor and bind to it.
It is made even easier using Unity or other containers.
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.
In my application I have several user controls in a window. These user controls need to communicate to each other. My approach is as below
user control A fire a command which is to be handled by user control B.
main window recieves the command and fire a command to B
user control B handles the command.
My problem is how the main window can fire a command which can be handled in the VIEW MODEL of user control B?
Update:
SOLVED: One gloabl static RelayCommand for communication from the MainWindow to B and one Global RoutedCommand for communication from A to Main Window. Thank you for the responses.
The question is not tagged mvvm (yet), but I am assuming it since you mention a ViewModel. So to begin with, let's agree that ViewModels handle commands, not controls. If a control want to respond to a command being executed, expose a suitable CommandExecuted event that the control (View) can attach a handler to.
There is however another unknown that I cannot blindly assume:
Do you take it for granted that user controls A and B exist at the same time? If yes, then a very simple and low-tech solution would be to maintain references to both ViewModels at some level (perhaps the ViewModel for the Window itself?) and "bubble" the command up to there, where the dispatch to ViewModel B will occur. If not (in which case control B might not exist), what is the desired behavior?
With the information you have given so far, I 'd suggest using the Event Aggregator/Mediator pattern implementation of your MVVM framework. For example, Prism has EventAggregator; MVVM Light has Messenger; etc.
I would think that you'd want to have a dependency property on B that the main window could bind to. Your DP on B would then take the request and call it's view model.
The main window should not know anything about the inner workings of a Control. It should only know about the exposed properties from the control.
I have a shell with some buttons and tabs and a few modules in my application. Each module has a view with some elements like datagrids, stackpanels, text boxes, etc. They all have a name attribute. Now when I fire an event on a shell (like click a button) I would like to be able to something with those elements (like clearing all the information written by the user in provided textboxes). The problem is, shell does not see those elements and cannot recognize them. Is there a way to access them?
Thanks for any suggestions.
I'd suggest you take an approach like what the Stocktrader Reference Implementation does with CompositeCommands. Basically a CompositeCommand is an implementation of ICommand that contains a collection of other ICommands. In the RI, the CompositeCommands are exposed as static properties on a centrally available class.
In your case, you could have a composite ClearCommand. The viewmodel for the shell would expose this to the shell view so you could hook up, say, your Clear button to it.
The viewmodels for the various modules would then hook into this ClearCommand:
GlobalCommands.ClearCommand.RegisterCommand(new DelegateCommand(x => ClearAllFields()));