我有一个超链接按钮,如果登录成功,我在按钮中点击内容后面的代码点击新视图。
private void OkButtonClick(object sender, RoutedEventArgs e)
{
LoginOperation loginOp = FLS.Utilities.RIAWebContext.Current.Authentication.Login(
new LoginParameters(usernameTextBox.Text, passwordTextBox.Text));
loginOp.Completed += (s2, e2) =>
{
if (loginOp.HasError)
{
errorTextBlock.Text = loginOp.Error.Message;
loginOp.MarkErrorAsHandled();
return;
}
else if (!loginOp.LoginSuccess)
{
errorTextBlock.Text = "Login failed.";
return;
}
else
{
errorTextBlock.Text = string.Empty;
Content = new WelcomeView();
}
};
}
我现在已经在视图模型中移动了MVVM的代码,并在超链接按钮上使用了delegateCommand。
<UserControl ... >
<Grid ... >
...
<HyperlinkButton Content="Login" Height="23" HorizontalAlignment="Left" Margin="313,265,0,0" Name="loginButton" Command="{Binding Path=LoginCommand}" VerticalAlignment="Top" Width="75"/>
...
</Grid>
</UserControl>
但我不知道,我如何制作Content = new WelcomeView();来自viewmodel中的代码?
答案 0 :(得分:0)
一个好的设计模式是拥有两个不同的数据模板,一个用于在登录前显示数据,另一个用于登录后使用的数据模板。
有几种方法可以实现这一目标。我通常使用的那个只是将ViewModel(直接使用绑定)放在Window的唯一子项中。
在ViewModel中实现内容选择器类。这是一个派生自DataTemplateSelector的类,它使用FindResource API来获取适当的数据模板。
<Window ...>
<Window.Resources>
<DataTemplate x:key="beforeLogin">
...
</DataTemplate>
<DataTemplate x:Key="afterLogin">
...
</DataTemplate>
</Window.Resources>
<Window.ContentTemplateSelector>
<code:MyTemplateSelector />
</Window.ContentTemplateSelector>
<-- Here is the content of Window. It's the view model (data). The View will be
bind by the TemplateSelector
<code:YourViewModel />
</Window>
查看此页面:http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplateselector.aspx以获取相关示例。
还有其他设计模式。另一个常见的习惯是简单地触发“UiRequest”事件,该事件将由视图的代码隐藏。请记住,MVVM规定ViewModel是“视图不可知”,但它实际上并不意味着“没有代码隐藏”。这意味着VM无法引用视图中的任何内容。通过这种方式进行通信会发生视图事件(例如,数据绑定只是属性更改事件的包装)。因此,在View Model中有一个事件UiRequest,并设计一个协议。在View的构造函数中 - 注册一个处理程序。在处理程序中,更改内容(人们使用这个成语主要是为了启动一个弹出窗口,但它可以在任何地方使用)。