I have one ViewModel and two Views. How can I navigate to View2 from ViewModel. I read somewhere that we need to use PRISM, for opening multiple Views from ViewModel in Silverlight. Is there any alternative for PRISM?
Ideally you do not want to use view logic in your viewmodel. Your viewmodel should not know anything about the view. It would be a better idea for your viewmodel to set a property letting the view know it's time to navigate. Here's an example:
ViewModel:
using System.ComponentModel;
namespace ViewModels
{
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private bool _DoneDoingStuff;
public bool DoneDoingStuff
{
get
{
return _DoneDoingStuff;
}
set
{
if (_DoneDoingStuff != value)
{
_DoneDoingStuff = value;
NotifyPropertyChanged("DoneDoingStuff");
}
}
}
}
}
View:
<navigation:Page
x:Class="Views.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:vm="clr-namespace:ViewModels">
<navigation:Page.Resources>
<vm:MyViewModel
x:Key="MyViewModelInstance" />
</navigation:Page.Resources>
<Grid
x:Name="LayoutRoot"
DataContext="{Binding Source={StaticResource MyViewModelInstance}}">
<i:Interaction.Triggers>
<ei:DataTrigger
Binding="{Binding DoneDoingStuff}"
Value="True">
<ei:HyperlinkAction
NavigateUri="AnotherPage.xaml" />
</ei:DataTrigger>
</i:Interaction.Triggers>
</Grid>
</navigation:Page>
Use a
DataTriggerwithBindingproperty set to theDoneDoingStuffproperty from your viewmodel, and theValueproperty set to "True". TheDataTriggerwill trigger whenDoneDoingStufffrom your viewmodel is set to true.Now you need a trigger action to navigate. Use
HyperlinkActionwith theNavigateUriproperty set to the page you're navigating to.Be sure to have System.Windows.Interactivity, System.Windows.Controls.Navigation, and Microsoft.Expression.Interactions assemblies in your references.
At first, this might seem to be too much, but your view logic is now where it needs to be.
You don't need to use PRISM, but it might be best.
One way that I have done it (and it is sloppy) is to have a MainView page that has a Navigation frame in it that will load the first view on start up. The MainView has to be a Page and not a UserControl. You need to have a navigation frame with uri mappings in the xaml and have a frame declared as shared/static in the code behind of the MainView Page and then set the loaded event (in the xaml) of the frame like so:
Public Shared MainContentFrame As Frame
Private Sub MainContentFrameXaml_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)
MainContentFrame = TryCast(sender, Frame)
End Sub
Then in the viewmodel you can just call:
MainView.MainContentFrame.Navigate(New Uri("/SecondView", UriKind.Relative))
This probably violates the MVVM pattern in some way and may not be a good way to do it, but it works. This is how I used to do it, now I use PRISM.
来源:https://stackoverflow.com/questions/9283441/how-to-navigate-from-one-view-to-another-view-from-viewmodel-in-silverlight