I have an application in PRISM, C#, and I wonder if I can do the following:
I've a button bar on the bottom of my appliction, which acts as my navigation area. The user can click on button A, and the dashboard of module A will pop up.
The user clicks on an item in the dashboard, and he comes to a details page about the item. He is in the pogress of making some changes, but he receives an email during this process.
He opens module B and makes a new item in module B.
--> There are 2 instances open at that moment, the details page of module A, and the add page of module B. I want the user to also visualy pick up on this, because there will be a "1" above the button for module A.
The question is, (how) can I do this with PRISM.
tl;dr; Does PRISM support multiple instanciated views? (it's the "managing" of open views, so you can chose which view to have open.)
I tried googling this, but I couldn't find anything related to it (probably because I'm not sure of how to call this, so I can't search on it :/)
Any info is much appreciated, thanks for your time.
Here's a very short intro on how this works out in Prism, including links to an unbelievably helpful section of MSDN:
Prism has regions, which is an abstraction for controls that can host one or more other controls (your views). Each region can have any number of views added to it, and at most one view in each region is active. The manner in which views (including what it means to be the active view) are displayed is dependent on the region adapter, which is an object created automatically by Prism based on what type of control hosts each region.
Adding to Jon's post.
You might want to use TabControl. If you put PRISM's region into TABCOntrol - you will be able to see all instances as tabs.
You can see decent sample with some XAML on how to close tabs here:
Menu service in Prism application CAL
So, on "inside" - PRISM will have either singleton views/viewmodels if you Export them with MEF by default. If you export those parts as NonShared - PRISM will keep multiple versions of same view inside container (MEF or Unity). However, with buttons - you won't get specific instance.
So, use TabControl as container like this:
Menu service in Prism application CAL
Or you can write your own region adapter and track instances in there.
Related
I have a simple database application where an user can add or delete persons. Moreover, the application has a button "Add new button to application". This application is built using Prism framework. There are two modules:
RibbonControlModule (contains three buttons - Add Person, Delete Person, Add new button to application)
PersonModule (contains logic of adding and deleting persons)
My requirement is to add new buttons at runtime.
Let's imagine a situation. I live in Washington and I am happy with these two buttons(Add Person and Delete Person). But my friend, Bob, who lives in New Jersey would like to add new button Edit Button without recompilation the whole application. That is, Bob writes dll where he can edit person and then clicks Add new button to application in RibbonControlModule. After that, EditPerson button is appeared in RibbonControl and, for example, in ContextMenu. Maybe EditPerson dll would be another Prism module, I do not know.
That is, my requirements are:
pluggable controls
is it possible to plug control without recompliation? (like add-ons or extensions(Classic Notes for Opera) in Browsers(no need to restart a browser to use add-ons))
other programmers can develop their add-ons without using my source code
after once an user plugged a control, then this new control should be always plugged in the application.
Is it possible using WPF, MVVM and Prism? I really like Prism and do not want to deny Prism, but if "the end justifies the means", I would like to use other technologies.
If it is possible, then how can I do it?
This is what the MEF plugin architecture was designed for.
In short, you create an SDK containing an interface for your plugins and provide that to your clients as a standalone library. Your client's plugins then implement this interface and export them with the MEF Export attribute, which your main application then imports.
Where it gets a little tricky is with data templating, which is often a key component of MVVM. To cut a long story short your plugins need to put their data templates in a resource dictionary, give that dictionary it's own partial class file and export it with MEF's [Export] attribute. Your main app then needs to import these and add them to the global ResourceDictionary's 'MergedDictionaries' array. This is generally done separate to all your view model classes which are imported in a separate pass. The net effect is that your plugins can provides both views and view models at runtime, plus the data templates that bind the two together, and it will all work as though they'd been statically compiled into your original application. It also means you can create a plugin API for your customers without exposing the internals of your main application.
This is a very involved topic, and given how general this question is I'll be surprised if this question isn't flagged. If you'd like more details then let me know and we can move it to a discussion page.
You can do what you are describing using Regions in Prism. You can add a named region to your Ribbon that allows Prism modules to plug in new buttons into that region when the module first loads or later when a user clicks a button in some UI of your module as you describe.
To do that, add an ItemsControl into some pane within your Ribbon where you want the plugged in controls to show up. Add the prism namespace as a XAML namespace like so:
xmlns:prism="http://prismlibrary/"
Then add the following attached property to your ItemsControl:
prism:RegionManager.RegionName="CustomModuleCommandRegion"
Then in your module, inject IRegionManager either in the Module class itself if the commands should be added as soon as the module is loaded, or elsewhere in a ViewModel if it won't happen until a particular view is loaded or some user interaction like you described:
public ConstructorForModuleOrViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
private SomeCommandHandler()
{
var commandButton = // create button and wire up command here)
_regionManager.AddViewToRegion(commandButton, "CustomModuleCommandRegion");
}
You also have the option of using the RegisterViewWithRegion method of the region manager to set up a factory method or just specify the type of the view (i.e. button) that you want to inject. But for a button you will need to wire up a command handler before (or after) placing it into the region, so the AddViewToRegion is probably more appropriate. If it is something that is context sensitive - i.e. you only want the button to show up in the ribbon perhaps when a selection is made in a view - then you can get the region from the region manager first, and then use the Add and Remove methods on IRegion to add and remove your view (button) dynamically like so:
IRegion region = _regionManager.Regions["CustomModuleCommandRegion"];
region.Add(myCommandView);
...
region.Remove(myCommandView);
Using the combination of Prism Modules and Regions you can achieve runtime extensibility of your app - i.e. this new functionality could be "dropped in" without needing to recompile the main app or other modules in the app. To do that you need to use either configuration to specify your modules so that can be edited in the deployed environment to add a module, or you can use the DirectoryModuleCatalog to scan a directory for modules on start up. Its even possible to use a FileSystemWatcher to watch a directory for modules that are dropped in while the app is running and have them light up immediately when placed in the watched directory.
I've searched online and was unable to find a specific answer to this question so I thought I'd asked. Sorry if I've missed the answer else where.
I work in an application that uses mvvm / prism framework and I'm wondering it it is possible to navigate to a view and then open a specific composite region within it allowing me to reach an end state that would normally taking clicking through a tab control.
Is this possible to do but only when I press a specific button rather than it be the default view navigation.
If so would I do with on initial navigation, or pass a parameter to the new view that says then navigate to the composite views.
Any help would be appreciated.
No. Regions are not controls. You can define a region in a control, say content control, and define what view will be associated with the region. Whenever the control become visible in the visual tree, the regions(the associated view) in the control will be visible.
I have iOS application with UITabBarController that contains UINaviagtionController for each Tab, like on the picture below.
I also want to port my application to WindowsPhone (>=7.5).
My question is: Which UI components/services can I use to create the navigation flow like in my iOS app?
Update
About UITabController you can think like about tabs in windows
The hierarchy of controllers that painted on the picture above mean that each tab in UITabController will have own UINavigationController (in the WP terms this is NavigationService). So if you will use the navigation on one tab this will not affect to navigation on other tabs.
But as far as I know by default WP application have only one instance of NavigationService.
So actually my question is relevant to a question: Can WP application use more than one NavigationService?
Windows Phone uses slightly different UI concepts. Instead of using Tab control you should use either Panorama or Pivot control. The former is used whenever you want to display completely disparate elements on a single large page, the latter is for displaying multiple views of the same data. This means that Panorama is used for displaying multiple views of different data.
Whenever you navigate from one page to another using NavigationService, it will keep the current stack. It serves as a history for the hardware Back button (unlike software button in iOS).
This means that you hold only one sequence of previously open pages in your application that can be navigated backwards, there cannot be any "side" stacks since they make no sense.
So if you were to navigate from one pivot item to some other application page, you would use the one and only NavigationService. Therefore each pivot/panorama item uses the same stack as the rest of the application.
If some things are still unclear, feel free to ask here.
I'm using Caliburn Micro for my project, and I decided to use Fluent Ribbon as part of the UI. My ShellView is really simple, and it's laid out like this:
Ribbon Control with 4 tabs.
ActiveItem.
The Active item is dynamically changed depending on the Ribbon's selected tab.
Question:
What is the proper way to use Ribbon control as a second view for my currently active ViewModel (ActiveItem), while maintaining modularity and all the goodies which come inherit with CM itself? Also, what would it take to "share" my Ribbon control among my ViewModels?
Details:
My ShellViewModel is of type "Conductor.Collection.OneActive", and it changes the ActiveItem to specific ViewModel I associate with selected tab (when event is fired).
My Ribbon is defined in XAML like this:
<ContentControl x:Name="RibbonBar" Micro:View.Model="{Binding ActiveItem}" Micro:View.Context="Ribbon" />
As it shows, Ribbon control is bound to currently active item as it's context view. That actually works for one view, because due to default CMs conventions, where it looks for the contextual views in the sub namespace (e.g. if my path to the view is Views.TasksTabView, it will look for the Context view at Views.TasksTab.Ribbon).
Problem is, when I change the ActiveItem, context view can't be located anymore, due to the different namespace, so It only works for one Tab.
I've also tried writing my own ViewLocator convention but I had no success with it.
Thank you.
Unfortunatelly since there are no answers, I'll answer it myself.
I did manage to write the additional ViewLocator logic to locate my Ribbon, but that created some problems (It seems that binding in CM only works once, so after Ribbon being located and bound to the VM, additional context view changes do nothing. There were some hard to find bugs as well).
I've taken a different approach then. I've separated Ribbon to it's own ViewModel, and composited it to the shell with rest of the modules. It uses EventAggregator and I also Inject it where neccessary. Not approach I was hoping for, but it works for now.
If anyone posts better answer, I'll definitelly accept that one.
I'm working on a windows 8 metro-style app, using developer preview for an academic project at university. We have to use MVVM pattern.
In the main Page we have a metro-style main menu with buttons. Each button leads to an application facility (ie. 'Show my Library', 'Show Favourites', ...) which should belong to a different View, according to MVVM pattern.
In your opinion should we create a new 'metro-style Page' for each View or expect a 'Scenario' for each use case refreshing the main Page, like those present in many example apps?
In other terms, using MVVM should there be a 1:1 match between 'plain old WPF Windows' and 'brand new metro-style Pages'?
The thing with MVVM is that there are no hard rules as to what constitutes a View other than the fact that it is the means by which the user can view the ViewModel data.
A View need not be a Page, but can be a Control. Thus you can have one page, on which many View controls are displayed, if you wish. Quite often I have my Views as controls, even if they are to be the sole item displayed on a page, as it allows me to embed them in other pages more easily at a later date.
The MVVM pattern is purely a means of separating the UI from the business/code logic. A ViewModel class doesn't care how it's data is displayed, it just provides the binding points, properties etc., for the data to be displayed and trigger points for code function.
Some people will insist that there is never any code in the code behind files, but I think that a more pragmatic approach is required. Code that controls visual aspects of the View is fine, and there are occaisions when what appears to be business logic intrudes.
For example when implementing drag and drop functionality code will be required in the code behind. This is really just a visual aspect so no problem there, but if the business model dictates that only certain items, or a maximum number of items are dropped in a given location then the ViewModel will need to provide some data binding points that the View can use to implement this. By doing so you could argue that the View code behind now implements some business logic.
So back to your original question. I would try to implement the application such that it behaves as is expected for a windows 8 metro-stryle application. This will obviously have a bearing on how you code, but it should still be possible to stick to the MVVM pattern when doing so.