There are 2 ways to do this, a simple way is to pass a relay command action from the view to the view model.
public MainPage()
{
var vm = new MyViewModel();
vm.GotoPage2Command = new RelayCommand(()=>{ Frame.Navigate(typeof(Page2)) });
this.DataContext = vm;
}
<Button Command={Binding GoToPage2Command}>Go to Page 2</Button>
Another way is by using an IocContainer and DependencyInjection. This one is a more losely coupled approach.
We will need an interface for navigation page so that we don't need to reference or Know anything about PageX or any UI element assuming that your viewmodel is in a separate project that doesn't know anything about the UI.
ViewModel Project:
public interface INavigationPage
{
Type PageType { get; set; }
}
public interface INavigationService
{
void Navigate(INavigationPage page) { get; set; }
}
public class MyViewModel : ViewModelBase
{
public MyViewModel(INavigationService navigationService, INavigationPage page)
{
GotoPage2Command = new RelayCommand(() => { navigationService.Navigate(page.PageType); })
}
private ICommand GotoPage2Command { get; private set; }
}
UI Project:
public class NavigationService : INavigationService
{
//Assuming that you only navigate in the root frame
Frame navigationFrame = Window.Current.Content as Frame;
public void Navigate(INavigationPage page)
{
navigationFrame.Navigate(page.PageType);
}
}
public abstract class NavigationPage<T> : INavigationPage
{
public NavigationPage()
{
this.PageType = typeof(T);
}
}
public class NavigationPage1 : NavigationPage<Page1> { }
public class MainPage : Page
{
public MainPage()
{
//I'll just place the container logic here, but you can place it in a bootstrapper or in app.xaml.cs if you want.
var container = new UnityContainer();
container.RegisterType<INavigationPage, NavigationPage1>();
container.RegisterType<INavigationService, NavigationService>();
container.RegisterType<MyViewModel>();
this.DataContext = container.Resolve<MyViewModel>();
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…