In MvvmCross is there a way to ask the navigation service to close to a specific viewModel?
For example let's say I have 3 view models
A B C
I have navigated from A to B to C.
A -> B -> C
In the C view I press a Done button and would like to go back to view A.
Is there a way to do something like this in the C viewModel?
_navigationService.Close<A>(this);
if you are on Xamarin.Forms (if not let me know and I'll update the answer because it's not that simple), in the IMvxNavigationService you have the ChangePresentation(...) method which uses a hint object to tell the framework what you want to do.
Task<bool> ChangePresentation(MvxPresentationHint hint, CancellationToken cancellationToken = default(CancellationToken));
Here you have the different out-of-the-box hints that the framework provides.
To address your issue you can just use MvxPopPresentationHint:
_navigationService.ChangePresentation(new MvxPopPresentationHint(typeof(A)));
or if A is your root ViewModel, you can just use MvxPopToRootPresentationHint:
_navigationService.ChangePresentation(new MvxPopToRootPresentationHint());
HIH
Related
Am using OnNavigatedTo for passing values while navigating between page, am getting the values in OnNavigatedTo.
That is working fine and now the problem is,
For sample i have screen A, B and C.
When i send data from A to B i can able to collect data in B.
So B has OnNavigatedTo method, when i navigate from B to C and come back to B OnNavigatedTo is called once when i come back to screen B.
Can some one help me to solve this problem.
In your OnNavigatedTo handler of screen B, you can check whether the navigation is backwards or a fresh navigation
if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
{
//Navigation is not backwards
//Your code
}
if i have this module structure:
ModuleA
*View/View_A
*Controller/ControllerA
ModuleB
*View/View_B
*ViewModel/ViewModel_B (view model for View_B)
*Controller/Controller_B
how could ControllerA use UriQuery to display View_B in a region
inside View_A
how could controllerB use UriQuery to display View_B in a region
inside View_A
which is better for displaying View_B in a region in View_A
Thanks in advance
I am not sure if I answer your question exactly. But I would recommend you to take a look at the Sample project that came with Prism2.2 -> Quickstarts - > UI Composition -> View Injection. This uses Unity and the example is in Silverlight and WPF.
This has the sample of how you can show the view from different module. It does not call the controller of the other project but calls the presenter.
IProjectsListPresenter projectsListPresenter = this.container.Resolve<IProjectsListPresenter>();
projectsListPresenter.SetProjects(employee.EmployeeId);
IRegionManager detailsRegionManager = detailsRegion.Add(detailsPresenter.View, employee.EmployeeId.ToString(CultureInfo.InvariantCulture), true);
IRegion region = detailsRegionManager.Regions[RegionNames.TabRegion];
region.Add(projectsListPresenter.View, "CurrentProjectsView");
detailsRegion.Activate(detailsPresenter.View);
Use the activate method to activate the view. Or if it is specific requirement/need to navigate, you can use detailsRegionManager.RequestNavigate with the UriQuery. (I have not tried request navigate myself :)
Additionally please review this post
http://compositewpf.codeplex.com/discussions/402860#post940396
Hope this helps.
Good Luck!
I have a viewmodel tied to a view used in a region. I'm trying to find a way that when that view is navigated to from a particular view (say view A), it does some work internally, like initializing some lists, setting some stuff, whatever. But if it has been navigated to from view B, it needs to NOT reinitialize everything, and just display the data it already has.
I could pass a parameter I suppose, saying whether this is a new operation or if we are going back to work on the old one, but I thought it would be nicer to be able to state that if we came from this view, we do one thing, and if we came from that one we do another.
If that makes sense :)
You can implement the INavigationAware interface which contains 3 methods. One of these methods is the OnNavigatedTo method. There you can access the journal and check the current entry. From there you should be able to determine if it came from View A or View B.
public void OnNavigatedTo(NavigationContext navigationContext)
{
var journal = navigationContext.NavigationService.Journal;
//use journal.CurrentEntry
}
Ok, so what I am looking to do is to display some sort of login control (maybe a UserControl with a TextBox and PasswordBox) when the app is started.
In a non-mvvm situation, a way of doing this would be to use the PopUp primitive control, add the usercontrol as a child element and off you go.
In an MVVM situation, i'm a bit confused about how you would achieve a simmilar result.
I have looked into messaging with the DialogMessage and this is fine for displaying a typical MessageBox, but what about a custom usercontrol?
any help would be fantastic! I can't seem to find any demo code of this anywhere.
In a MVVM situation you can use a delegate to let your View open the dialog when the ViewModel requests it.
You define a delegate at the VM:
public Func<LoginResult> ShowLoginDialogDelegate;
In your View you define the function that will be called:
private LoginResult ShowLoginDialog()
{
LoginResult result;
// show a dialog and get the login data
return result;
}
Then you "connect" the delegate and method in the View:
_viewModel = new MyViewModel();
DataContext = _viewModel;
_viewModel.ShowLoginDialogDelegate += ShowLoginDialog;
And now you can use it in your ViewModel e.g. when a command is executed like that:
LoginResult result = ShowLoginDialogDelegate();
An easier answer is to control it's visibility through a View State which with a little manipulation can be made to work through databinding allowing the view model to display the "Logon Page" state when required.
I just recently wrote about this for the Silverlight/XNA series which you can view here.
It would be much simplier if the SL4 DataEventrigger was available but hay ho.
In my winforms app, I have a UserControl that contains a DataGridView. I instantiate and load this UserControl when needed into a panel in my Main Form (frmMain). My problem is figuring out how to resond to or listen for events raised in my UC's DataGridView. For example, I want to handle the CellDoubleClick event of the DataGridView in my Main Form rather than through the UC.
Is this possible? I had thought of updating a property when the cell in the grid is double-clicked, and then let my Main form do whatever when that property changes - therefore I thought of using INotifyPropertyChanged. Im not heavily clued up on how to use it in m scenario however, and would deeply appreciate some help in this regard, or if anyone can suggest an alternate solution.
Much thanx!
Your user control must encapsulate some logic, so if you want to handle event of the DataGridView that is in your control the way you've described, you probably missing something in idea of user controls and encapsulation. Technically here two ways to do this:
Make a public property in your user control of type DataGridView.
Make an event wrapper. You will need to create an event in your user control that is raised when DataGridView CellDoubleClick (or any) is rased and in your calling code you will handle this event wrapper.
The second approach is more logical, cos internal logic of your control is incapsulated and you can provide end-user of you component with more logical and meaningful event then CellDoubleClidk or else.
thank u 4 your reply. Sorry for not responding earlier. I did manage to sort this issue out by creating a public event in my UC:
public event DataGridViewCellEventHandler GridRowDoubleClick {
add { dgvTasks.CellDoubleClick += value; }
remove { dgvTasks.CellDoubleClick -= value; }
}
and in my main form, after I instantiate and load the UC
_ucTask.GridRowDoubleClick += new DataGridViewCellEventHandler(TasksGrid_CellDoubleClick);
with the following attached event:
private void TasksGrid_CellDoubleClick( object sender, DataGridViewCellEventArgs e ) {
// do work here!
}
This does work, although I don't know if any of u experts out there foresee a problem with this approach.