WPF Navigation between child views - c#

I have an application that consists of a shell, a content control that acts as a region and child content controls that goes into that. When the application loads, it starts in a file load view, and once a file is loaded a new region view is navigated to and appropriate child views. The problem I'm having is getting back to the file load view. I can get it to navigate to the file load view, but IsNavigatedFrom isn't called in the child view's VM, and this is causing problems because the child VM has ConfirmNavigationRequest to make sure that the user actually wants to leave that particular view.
Any ideas?
[edit] The button to go back to the file load view is in the parent content control. I've tried putting it in the child but it causes too much redundancy[/edit]

The IsNavigatedFrom will be called in the object that was used by your "RequestNavigate".
If you called RequestNavigate(view), then you can define IsNavigatedFrom in view.
If you want IsNavigatedFrom called in the ViewModel, then you need a viewmodel-first navigation.

Related

What is the best approach to create a Visual Studio-like Start Window using ReactiveUI?

I want to make a Start / Welcome / Solution selection window which has similar functionalities to the one used in VS19 / VS22, but I'm not sure how to do it exactly.
For more context, my current StartWindowView has a "Create New Project..." button, which should replace the entire window content with a 2-page project creation wizard.
Page 1 should be "Basic Options" where on the bottom there are "Cancel" and "Next" buttons ("Cancel" goes back to the original StartView and "Next" goes to Page2View).
Page 2 should be "Extra Options" where on the bottom there are "Back" and "Finish" buttons ("Back" goes back to Page1View and "Finish" goes back to the StartView, returning a ProjectModel)
From my understanding, these are the ViewModels I'd have to deal with:
StartWindowViewModel // Main window host (possible router)
StartViewModel // Main project selection view
ProjectCreationViewModel // Possible router for Page1 & Page2
ProjectCreationPage1ViewModel // Basic options
ProjectCreationPage2ViewModel // Extra options
My idea was to use Routing, but I don't know if that's the right approach, since I'm not sure if the data between Page1 and Page2 will be preserved when going back and forth.
Also, the routing examples I saw for ReactiveUI have fixed "Back" and "Next" buttons on the bottom, therefore it makes me think that this might not be the solution for my problem, since pressing the "Create New Project..." button replaces the StartViewModel with the ProjectCreationViewModel, making manual navigation impossible.
I might be completely wrong though. I'm really unsure on how to approach this problem.
EDIT: This is how the VS22 start window looks like:
and this is what happens when you press the button marked in red:
As you can see, the entire window changes the current View.
It's not terribly difficult, just keep an observable collection of your view model stack, and always display the last one (or the first one, it's easier with WPF bindings). Note that I'll be referring to this as a stack, but there is no ObservableStack<> already built for you. Either use an ObservableCollection<> or build your own observable stack.
Then as you need to navigate "into" your wizard (new project, clone a repository, etc), you simply push the new child view model onto the stack. When you need to navigate "out of" your wizard (ie, on Cancel), pop the last view model from the stack.
The last step is to associate your views to view models (using DataTemplate in a high-level resource block, either a global one or a local one in your start page) and then bind your view model stack's top to your main window (the shell that has a ContentControl bound to the top of your stack).

Transition between views by navigation controller. ignoring tabbarcontroller

There is a problem , I have one available repose collection ViewController. At the same representation have a button switch to another View. Between the repose organized transitions (navigation controller). Clicking on the back button in the second presentation is called ViewDidAppear is good. But I also have an application has tabBarController. And when you click on the first View on the panel tabBar called again ViewDidAppear. Although he no longer needs to be called . Tell me how can I do so that does not cause tabbar ViewDidAppear. A caused only navigationController? Thank you!
ViewDidAppear will be called every time a ViewController is displayed is shown on the screen.
ViewDidLoad is called only when the View is loaded. So for example, if you present a modal view from a view controller (parent vc), then when the modal is dismissed, the parent vc will NOT have its ViewDidLoad method called. Instead it will have ViewWillAppear and ViewDidApper called only.
Moving the code you only want called once to ViewDidLoad should solve your problem.

TileControl Devexpress

I have developed an application using TileControl
and on Clicking the Tiles, it is navigating to forms.
The forms contains GridControl and when I am performing double click event on gridview,it is navigating to another form and displaying a result.
Now the Problem is, when i am clicking the back button of Tile Menu,it is directly showing the main menu,instead of form having GridControl.
I want to show the GridControl first and then the Main Menu.
Please help me with a solution.
I far as I can see you are using the DocumentManager and it's WindowsUIView.
To make it possible to navigate back from the current screen(with item detail) to upper level(with grid) you should make the current content container aware to it's parent container via ContentConteiner.Parent property.
Thus your containers hierarchy should looks like this:
// mainTileContainer(MainMenu)
// -> gridItemsPage(GridControl)
// -> itemDetailPage(DetailForm)
//...
mainTileContainer.ActivationTarget = gridItemsPage;
gridItemsPage.Parent = mainTileContainer;
itemDetailPage.Parent = gridItemsPage;
Related links:
Content Containers
Hierarchy and Screens
How To: Create Content Containers Hierarchy

instantiate navigationservice class

I was working on a WPF project today that had a main nav window and then 4 pages that were loaded within this main window (using NavigationService.Nagivate...).. Within the XAML this created a lot of duplicate code so I wanted to refactor the menu into a user control that I could then bind to each page. I tried to create a class to handle the navigation and loading of each page but I discovered that NavigationServices is a sealed class and cannot be instantiated.
Would anyone please provide a suggestion/solution on how to create a usercontrol with a menu item that will allow the ability to navigate to new pages within the project. I have been able to do this within pages and the direct code behind but I have not had any luck trying to separate the two. If this is too vague please let me know and I will provide more deails with code samples.
Thanks in advance
Create a NavigationService dependency property on your user control. Then, when you instantiate your control, bind this property to the NavigationService of the container where the navigation should occur. For example, a page might display the user control like this:
<local:NavBox NavigationService="{Binding NavigationService, RelativeSource={RelativeSource AncestorType={x:Type NavigationWindow}}}" />
Now when your UserControl calls Navigate on its NavigationService, that will effectively call Navigate on the containing NavigationWindow's NavigationService. (This can be modified in the obvious way to support Frame or Page instead of NavigationWindow.)

WPF and Prism View Overlay

I need some help with overlaying views using the prism framework.Its a little more complexed than that so let me explain.I could be over-thinking this as well :D
i have shell (wpf window) and i have 2 views(A & B - both usercontrols) in a module.
when the shell loads it loads view A. On view A i have a button to "popup" view B
for some user input. so naturally i would think to some sort of modal window/control, maybe even a popup. however the problem i face with the popup is that when i move the shell the popup remains fixed and it doesnt block events in view A. I've tried disabling view A to stop events being fired and i've also tried to use a to get the view B move with the shell. Only the canvas works but i now need a way to block it tho'. Is there anyway i can overlay a view on top of another view with prism? or how does everyone else create modal popups with prism & wpf? any advise or pointers would be greatly appreciated.
If you want to use embedded dialogs without an extra window, you can use Prism's RegionManager to achieve the outlined behavior. The trick is to put the PopUp region parallel to your main region in the visual tree:
<Grid>
<ContentControl cal:RegionManager.RegionName="MainRegion" IsEnabled={Binding IsNoPopUpActive} />
<ContentControl cal:RegionManager.RegionName="PopUpRegion"/>
</Grid>
Now use the RegionManager to put view "A" into the "MainRegion". Create a controller class similar to IPopUpDialogController. It should be responsible for putting your view "B" (or any other PopUpView in your application) into the "PopUpRegion" on demand. Addtionally, it should control a flag that signal the underlying "MainRegion" to be enabled or disabled. This way a user won't be able to play with the controls in your view "A" until the pop up is closed.
This can even be done in a modal fashion by using ComponentDispatcher.PushModal() before pushing a frame onto the Dispatcher. However, I would recommend avoid modal dialogs.
Update: As requested in a comment, the IsNoPopUpActive could be implemented in the backing view model. There you could link it to RegionManager's View collection for the popup region:
public bool IsNoPopUpActive
{
get { return _regionManager.Regions["PopUpRegion"].Views.Count() == 0; }
}
Remember to trigger a PropertyChanged event as soon as you modify the views collection (add/remove a popup).
Just for your information: nowadays I avoid disabling the controls in the background and instead insert a transparent panel. This avoids clicking on background controls. However, this does not handle keyboard input (tab-ing to controls). To fix the keyboard input you need to make sure that the keyboard focus is trapped in the popup (MSDN on WPF Focus concepts).
Adding the following focus attributes to the popup region should do the trick:
KeyboardNavigation.DirectionalNavigation="None"
KeyboardNavigation.ControlTabNavigation="None"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.TabIndex="-1"
If you are using WPF + MVVM with Prism you can take a look at this Message View overlay controller. The nice part about this approach is you can write unit tests on you view model using a mock overlay controller and have the mock controller return the result that the user would choose in the overlay.
You can find it here: http://presentationlayer.wordpress.com/2011/05/24/wpf-overlay-message-view-controller/
Hope this helps

Categories