我有一个Silverlight 4项目,它显示一个图表和一些按钮,允许用户更改图表的日期范围。日期范围也可以通过查询字符串参数传递 - 类似于http://myserver/MySilverlightPage/#?DateRange=OneMonth - 当用户点击按钮时我也想更新Url。
我知道这样做的方法是调用this.NavigationService.Navigate(new Uri(...))
,但据我所知,这只能从后面的Silverlight页面代码中完成。由于我使用的是MVVM,因此命令的所有处理都在ViewModel类中进行。有没有办法在ViewModel中调用Navigate
或以其他方式更改Url?
为了澄清,xaml包含以下Button
:
<Button Content="1 Month View"
Command="{Binding OneMonthCommand}" />
ViewModel类包含OneMonthCommand
属性:
public ICommand OneMonthCommand { get; set; }
单击该按钮时,将调用ICommand实现的Execute
方法。问题是 - 如何从该方法中更改Url?
答案 0 :(得分:8)
我发现这是我使用MVVM模式编写的Silverlight应用程序中的常见问题。我使用NavigationHelper类来集中导航逻辑。它看起来像这样:
public interface INavigationHelper
{
void Home();
void SomeOtherPage();
}
public class NavigationHelper : INavigationHelper
{
private NavigationService _navSvc;
public NavigationHelper(NavigationService navSvc)
{
_navSvc = navSvc;
}
public void Home()
{
_navSvc.Navigate(new Uri("/Home", UriKind.Relative));
}
public void SomeOtherPage()
{
_navSvc.Navigate(new Uri("/SomeOtherPage", UriKind.Relative));
}
}
然后,我让ViewModel有一个NavigationHelper属性,该属性是在构造ViewModel时由页面设置的。
顺便说一下,看起来在ViewModel的构造函数中传递NavigationHelper会更简单。但根据我的经验,拥有ViewModel的非默认构造函数会使得在Blend设计时更难以使用它。答案 1 :(得分:2)
如果您只是进行常规导航,则应使用常规的HyperlinkButtons。如果您尝试导航以响应其他事件,那么您可以使用消息传递。
另一种方法是让View将NavigationService类传递给您的ViewModel,如果您使用基页和基本视图模型,您将能够在不需要每个视图模型的情况下实现它并查看了解交接发生。
答案 2 :(得分:1)
使用MVVM并不排除使用超链接按钮,如果他们能够完成您需要的工作。
正如您所发现的,NavigationService.Navigate的问题在于它需要了解页面的上下文。
当你在codebehind中设置datacontext时,我不认为将当前视图注入其视图模型是“太邪恶”。通常情况下,View对其ViewModel知之甚多。