我关注了 Robert Garfoot 的博客“Silverlight Navigation With the MVVM Pattern”。
它允许您以一种不同的优雅方式从页面的代码隐藏中进行导航处理。
他使您的 ViewModel 可以使用 Navigate、GoBack 和 GoForward,因此您可以让代码隐藏没有导航代码。
它工作得很漂亮。
但是我想从 ViewModel 访问一些事件(Navigated、Navigating、NavigationFailed 等)。我不知道该怎么做。这是使用接口和掌握 c# 的问题。
对不起,如果它有点长,但我会尽量让它简短:
我将把所有这些类放在一个名为 LibrariesSL.MVVMNavigation 的命名空间中:
他创建了一个 INavigationService 接口:
public interface INavigationService {
void NavigateTo(string url);
void GoBack();
void GoForward();
}
NavigationService 类:
public class NavigationService : INavigationService {
private readonly System.Windows.Navigation.NavigationService _navigationService;
public NavigationService(System.Windows.Navigation.NavigationService navigationService) {
_navigationService = navigationService;
}
public void NavigateTo(string url) {
_navigationService.Navigate(new Uri(url, UriKind.Relative));
}
public void GoBack() {
...
}
public void GoForward() {
...
}
}
然后是用于扩展 ViewModel 的 INavigable 接口:
public interface INavigable {
INavigationService NavigationService { get; set; }
}
在 ViewModel 中,我们只是继承并使用它:
public class CustomerViewModel : ViewModelsBase, INavigable {
MyDomainContext _Context = new MyDomainContext ();
...
...
public void OnShowCustomer(object param) {
int selectedCustomerID = SelectedCustomer.CustomerID;
// Here we perform navigation
NavigationService.NavigateTo(string.Format("/CustomerDetails?CustomerID={0}",
selectedCustomerID));
}
#region INavigable
public INavigationService NavigationService { get; set; }
#endregion
我们还必须创建一个附加到视图的依赖属性:
public static class Navigator {
public static INavigable GetSource(DependencyObject obj) {
return (INavigable)obj.GetValue(SourceProperty);
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.RegisterAttached("Source", typeof(INavigable), typeof(Navigator),
new PropertyMetadata(OnSourceChanged));
private static void OnSourceChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e) {
Page page = (Page)d;
page.Loaded += PageLoaded;
}
private static void PageLoaded(object sender, RoutedEventArgs e) {
Page page = (Page)sender;
INavigable navSource = GetSource(page);
if (navSource != null) {
navSource.NavigationService = new NavigationService(page.NavigationService);
}
}
}
然后在视图中我们这样做:
<navigation:Page x:Class="UsingQueryStrings.Views.Customers"
...
xmlns:MVVMNavigation="clr-namespace:LibrariesSL.MVVMNavigation"
MVVMNavigation:Navigator.Source="{Binding}"
>
我想访问 System.Windows.Navigation.NavigationService 中存在的事件 Navigated、Navigating 和 NavigationFailed。