WPF prism accessing view elements from shell - wpf

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()));

Related

Should I dependency inject? How do I do it?

Okay, so I am working with Microsoft Prism in WPF using a MVVMC(or MVCVM) pattern.
In my ChatModule I have a series of Views, ViewModels, and one Controller.
For the Views I have
ChatAreaView - Displays the chat messages that come in to be read. This is hosted inside of a TabControl region so that I can have chat windows between the user and other users, or maybe file transfer windows, etc.
UserAreaView - This is a list of the users. Right clicking has context menu to interact with them... like sending a file or whispering.
MessageAreaView - This is where the user types in messages to be sent to all of the others.
For each view, I have a corresponding ViewModel. ChatAreaViewModel, UserAreaViewModel and MessageAreaViewModel. These ViewModels essentially only contain properties.
For example, the UserAreaViewModel defines a struct of type User which is essentially just a Name. Actually this is defined outside of the class, but still... it uses it. It has an ObservableCollection to store a list of all the Users who are currently connected. It also has ICommand properties defined to interact with the user. Right now I have SendFile, Whisper and Nudge... with intent on adding more in the future.
The Controller creates these views and ViewModels, and marriages them. It news them up, assigns the ViewModel as the corresponding View's DataContext, and sets all the initial properties of the ViewModel. Over the lifetime of the module, it will react to user interaction and execute DelegateCommands that it has assigned to each of the ViewModel's ICommand properties. These will further alter the state of the properties in a ViewModel.
I am using the actual types of Views and ViewModels, instead of interfaces, like such.
#region Views
ChatAreaView viewChatArea;
UserListView viewUserArea;
MessageView viewMessageArea;
LoginPromptView viewLoginPrompt;
#endregion
#region ViewModels
ChatAreaViewModel viewModelChatArea;
UserAreaViewModel viewModelUserArea;
MessageAreaViewModel viewModelMessageArea;
LoginPromptViewModel viewModelLoginPrompt;
#endregion
Would things be a lot more neat, less coupled if I defined interfaces for the Views and ViewModels, and operated on these interfaces within the controller instead of the concrete implementations? Could I then just register them with my Container in the Module class(which is essentially the root of each Module)?
What do I have to gain from doing this? How would I implement an interface for each view to distinguish them from the others? They don't really do ANYTHING except have XAML... and teh ViewModel's don't really do anything either except have certain properties. And those properties might be subject to change. On the UserAreaViewModel for instance, I will definitely want to add more commands so a user can interact with another user in different ways.
Can somebody help me out here? In my mind I'm thinking I should be abstracting this stuff, but I don't really know a logical way I should be going about it, or even if it's a wise idea to do so. What do I have to gain?
Thank you for your time. The below image is an example of what I'm working on. Ignore the Add new Item button and the styling of everything... that's not what I'm working on right now.
loosely coupled - can replace an entire class with altogether different implementation in future.
independent development.. can inject a dummy UI / view until final UI gets ready. two pieces can evolve at the same time (after having a common contract).
no need to add references to the modules (implementing the view). can use ConfigurationModuleCatalog to discover types from config file.

WPF/Prism: Nested views and toolbar

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.

Using MVVM in WPF, should I launch child windows from View code behind, or ViewModel?

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.

Prism/MVVM (MEF/WPF): Exposing navigation [Menu's for example] from modules

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

Model-View-Presenter and Modal Dialog boxes.... How to?

I am implementing MVP/M-V-VM in WPF and I'm having good luck with it so far. However, I don't see how this model supports implementing Modal dialog boxes. I've derived my work from Crack.NET (http://www.codeplex.com/cracknetproject) to learn how this stuff works.
I have a ShellView view (which is just XAML) that has a menu on it. The menu binds to a command in the ShellModelView that says "EditPreferences".
The ShellModelView implements the ICommand for EditPreferences and here we want to put up a dialog box to let the user edit preferences for the application.
Several problems here:
1. The ShellModelView doesn't have a reference to the ShellView to properly parent the dialog. The ShellModelView is the DataContext of the ShellView but I don't see a backreference that's setup.
2. The ShellModelView shouldn't be loading explicit UI anyway. So what's the proper interaction model here?
3. How do I build up my PreferencesDialog so that it's properly separated between logic and view as well? PreferencesDialog itself needs to be a Window so you can call ShowDialog on it, but that means you need a reference to the Window (e.g. View) in order to instantiate it. Ideally I should be able to unit test the code/validation within PreferencesDialog without instantiating the view (using a Mock view perhaps?).
Perhaps this is not the appropriate way to look at it, but this is the approach I take with M-V-VM in WPF. Opening windows and dialog boxes or an "EditPreferences" view are UI specific functions. If I were to rewrite the your entire UI replacing all of the views, I may wind up combining the "EditPreferences" view with another view, and therefore never want to open it in another screen. If this were tied to the ViewModel, it would be difficult to get around. In this particular situation, I would have a button or menu item in my "ShellView" that creates a new instance of my "EditPreferences" view, and then passes in the "EditPreferences" ViewModel which may either come from a property in my "ShellViewModel", or perhaps my "EditPreferences" view instantiates the ViewModel itself.
Here is a similar question on SO that basically says the same thing: M-V-VM Design Question. Calling View from ViewModel
You will need a controller in your case. The controller should be in charge for showing the preference dialog window.
As I can envision it the controller should be responsible for creating the ShellModelView and binding view's DataContext to it. The controller should be also responsible for handling command execution of EditPreferences. In the execution logic the controller will create a new PreferencesDialog and its corresponding view model.
You can find similar patterns in Prism if you haven't already did it. You can also reuse the DelegateCommand provided there :)
Have the PreferencesDialog implement a interface that is one of the properties of the EditPreference command. The command would interact with the dialog through the interface. For Unit Testing the mock object would implement the interface instead.
The dialog class then can reside on your highest layer.
My 2 cents is:
Pass some kind of viewfactory contract as the command parameter or inject a viewfactory contract into the view model. The view model will them use the viewfactory to create any modal/non modal views it needs. The viewfactory could also take in as a parameter of its Show/ShowModal method a viewmodel to display. Furthermore, the viewfactory could use a datatemplate to display any viewmodal passed in as a parameter.
Add a ShowViewModel property to the viewmodel in question. A DataTrigger could then watch for this property and when it is of a particular type show the view, etc.

Resources