This answer can be in either Prism and/or Caliburn.Micro. Changing user control in the main shell can be done with something like this:
Prism
_regionManager.RequestNavigate("ContentRegion", uri);
Caliburn.Micro
ActivateItem(new ViewModel());
But my question is, how can you change the user control that is shown in the shellview upon clicking a button inside another user control?
You can use the exact same line (for Prism, at least) in any command anywhere. In case your're wondering how to get the _regionManager - just have it injected as constructor dependency.
Related
When using code behind, the code looks like this:
AnotherWindow x = new AnotherWindow();
x.Show() ;
// or x.ShowDialog()
But how can I achieve this using MVVM? Specifically Prism?
In case you need to build a dialog for asking user login input or progressing dialog, MahApps.Metro can be a useful toolkit as it provides you with some built-in dialog UI/functionalities with MVVM pattern. For more information, check some examples here:
https://mahapps.com/controls/dialogs.html
In Prism, there's the InteractionRequest for short-lived dialogs. If you're looking for a long living dialog, like a second application window or shell, you're stuck with new Window ... Show.
To make your dialog service mvvm-friendly, you should hide it behind an interface and make it as generic as possible. Using view model first here eliminates the need to specify a window type, because you can provide a default window that just contains one large ContentControl, and the view can be mapped as DataTemplate.
I'm relatively new to UWP, but I have good WPF background.
What I need is a simple context menu for the application. User "right taps" anywhere, menu opens, user taps an item and things happen.
It looks basic and simple. First I add MenuFlyout element to my Application.Resources. Then, in MainPage I just show it with ShowAt method. Works.
To my greatest surprise when I tried to add events to menu items, VS told me it's invalid, events cannot be added in App.xaml.
So here's my assignment (in App.xaml.cs):
MainContextMenu = (MenuFlyout)Resources["MainContextMenu"];
MainContextMenu.Items.First(i => i.Name == "NavToCalibration").Tapped += NavToCalibration_Tapped;
The problem is - the handler is never called. I run my app, open the menu, click on the item and nothing happens. The assigned method is not called. What am I doing wrong? Why the handler is not called?
The assignment IS executed on application launch.
I'm also surprised I haven't been able to find any example or tutorial on doing such a simple and basic thing.
There is a good reason I use app-wide context menu instead of other controls. The app displays test images, it has to be full-screen (or maximized window) without interfering elements.
Now I will try to move my menu to the page resources, my pages will have different context menus anyway. But I'm really curious what's wrong in MenuFlyout defined in App.xaml?
Whoa. I tried to move my MenuFlyout to MainPage. I was able to assign Tapped event in XAML. And it also is not triggered! Now I'm completely lost. Any ideas?
I have a a PopUp with a Region that contains another Region. This popup is invoked through the WPF Prism(MEF) InteractionRequest methodology. The structure looks like so:
PopUpUserControl
- ContentControl : Region(UserCatalogsCreateRegion)
- PopUpStageUserControl
- StackPanel
-ContentControl : Region(UserCatalogsCreateStackRegion) <--Disappearing Region
The problem manifests itself like this. When the application starts up and is running normally, I can list the Regions in the application and I can see that the RegionManager contains the Region named "UserCatalogsCreateStackRegion".
Now when I click the button that sets off the InteractionRequest for PopUpCreation, I can see that the list of Regions no longer contains "UserCatalogsCreateStackRegion". I verified that something is removing my Region because I added a CollectionListener to the Regions property of the RegionManager, and as soon as the Popup is created, my breakpoint is hit and the Notif..Action is "Remove" and the OldItem is the Region in question.
TL;DR Region disappears from RegionManager.Regions when the popup that contains said Region is created and invoked.
Any help is greatly appreciated. And I will try to answer as many other questions as possible as there is A LOT that can go wrong with a Region manager.
EDIT
Brian Lagunas' links pointed right to the doggone solution. This was the solution. My final working code for the PopUpStageControl looks like this, where ContentControl is the Region that kept "disappearing":
[ImportingConstructor]
public PopUpStageUserControl(IRegionManager regionManager)
{
InitializeComponent();
this.regionManager = regionManager;
//Fix Begin
RegionManager.SetRegionName(ContentControl, AppRegions.UserCatalogsCreateStackRegion);
RegionManager.SetRegionManager(ContentControl, regionManager);
//Fix End
RegionManager.SetRegionManager(this, regionManager);
RegionManager.UpdateRegions();
}
This is because a popup is not part of the visual tree, so the region manager will not be able to find the region. You will have to manually register the region. See these posts:
Region not loaded by the RegionManger
How to register regions inside user controls or control templates in RegionManager?
PRISM 6 Regions in WPF using DataTemplate/CustomControl
https://github.com/PrismLibrary/Prism/issues/251
Going off of my comment and then a quick Google result (old version of PRISM).
The IRegionMemberLifetime interface: Note also that the ModuleARibbonTab class implements the IRegionMemberLifetime interface. This interface is provided by Prism, and it controls whether a View is removed from a region when the user navigates away from the View.
By the sounds of it you might want to implement IRegionMemberLifetime and set KeepAlive appropriately--that might have an effect on when the RegionManager removes/persists the region.
Although you do not stated it in your posted code, I assume that you are using something like this when setting up InteractionRequest:
<prism:PopupWindowAction.WindowContent>
<inf:PopUpStageUserControl/>
</prism:PopupWindowAction.WindowContent>
So you have to be aware that at runtime Prism will replace all popup content with the one you specified in PopupWindowAction.WindowContent.
I am trying to create a simple onscreen keypad created using buttons (currently a User-control), on those buttons i have a click event, when i click/touch a button i want the value of that button sent to a Text-block in my Main-window.
I can't/don't understand how to make the User-control (keypad) see the Text-block (in Main-window) to add in the value that i need.
I have seen solutions that use command Bindings and solutions that use the visual tree traversing but all of them are the main window accessing the user control, not the other way around.
All the examples are the other way around because that is how a UserControl is supposed to work.
A UserControl is a packaged piece of re-usable functionality. It should not know anything about the code that is using it.
Instead you should expose routed events in your UserControl for things like a when number was selected, and subscribe to them in your main window.
There are many ways to achieve what you want. If your MainWindow.xaml has a UserControl and you want to react to a change from the control in the MainWindow.xaml.cs file, then you could add a delegate to the UserControl code behind and register a handler for it in the MainWindow.xaml.cs file. Implementing new delegates are generally somewhat simpler than implementing RoutedEvents, which is another way that you could handle this situation.
Using a delegate like this will enable you to effectively pass a signal to the main view from the child UserControl code behind, which you can react to in any way you want to. Rather than explain the whole story again here, please see my answers from the Passing parameters between viewmodels and How to call functions in a main view model from other view models? posts here on Stack Overflow for full details on how to achieve this.
I'm currently very stuck with this, my designer wants to have our app with WindowStyle.None to remove the borders and default ugly controls, he has then add custom controls, usually to allow dragging in the past we have used a rectangle and monitored the mousedown event to allow for dragmove.
However with Caliburn micro we lose control of the window because windowmanager create this for us, I'm aware you can override the create window method, but this still doesn't give access to adding UI elements to the window itself and binding to those events. Or at least i can work out a way to do this.
Basically what we are trying to achieve is the "mainwindow" with a WindowStyle.None and that ability to drag and move the window. My googling has failed to give a solid answer on this, and im hoping someone here has an idea.
Caliburn.Micro doesn't force you to make the all your views UserControls. The main view or the one your showing as the main window can be a Window control and you can set properties directly on that Window such as "WindowStyle.None". When Caliburn.Micro sees that the view behind your main view model (the view model you are using as the root, then one you are creating first) is actually a Window and not a UserControl then it will honor this and show that window, It Will Not create a new Window. So you can set your properties directly on that Window and everything shall work fine.
The Caliburn.Micro WindowManager provides overrides to its Show methods that allow you to set the settings of the window that is created.
Have a look here for an example.
Alternatively, you can use a Window directly as your view type (in XAML and the generated code behind file), and set the properties declaratively in the XAML.
If you wish to enable all of your dialogs etc to have common UI components, then you could create a derived WindowManager type that delegates the call to the CM WindowManager but wraps the passed in view model with your common view model. Then register this custom window manager in the bootstrapper rather than the default CM window manager.