问题
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?
回答1:
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
DataTrigger
withBinding
property set to theDoneDoingStuff
property from your viewmodel, and theValue
property set to "True". TheDataTrigger
will trigger whenDoneDoingStuff
from your viewmodel is set to true.Now you need a trigger action to navigate. Use
HyperlinkAction
with theNavigateUri
property 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.
回答2:
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