根据状态在视图之间切换

Uri*_*Uri 3 wpf mvvm

假设我有一个显示用户好友列表的应用程序.好友列表以TabItem显示.用户必须首先登录到服务器,以获取朋友列表.

我创建了两个用户控件,一个用于用户登录时,另一个用于未登录时.这条线上的东西:

UnloggedView.xaml

<UserControl x:Class="UnloggedView" ...>
    <TextBlock ...>You need to <Hyperlink Command="{Binding LoginCmd}">
        Login</Hyperlink>too see your friends list</TextBlock>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

LoggedView.xaml:

<UserControl x:Class="LoggedView" ...>
    ...
    <ListView ItemSource={Binding Path=friends}">...
</UserControl>
Run Code Online (Sandbox Code Playgroud)

主窗口包含以下代码:

....
<TabItem Header="Friends">
    <vw:UnloggedView />
</TabItem>
Run Code Online (Sandbox Code Playgroud)

我相信一切都是根据MVVM的原则.LoginCmd是在ViewModel中实现的DelegateCommand(来自prism)的简化变体.两个视图都正常工作,并且在填充(异步)列表时,会触发通知并更新视图.我很高兴.

所以我有两个问题:第一个问题是我如何激活LoginWindow(提示用户输入他的凭据?现在,我只是创建LoginWindow(一个视图对象)并使用ShowDialog呈现它.它看起来像我通过直接操作ViewModel中的UI来打破MVVM的规则.

主要问题是在我使用服务器登录后,用LoggedView替换TabItem内容的正确方法是什么.根据MVVM主体,ViewModel不应该对View的内部有所了解.我在ViewModel中暴露了IsLogged属性(它将触发PropertyChanged通知)但是我应该绑定什么才能使一切发生?我真的不希望ViewModel操纵View.

谢谢

Rac*_*hel 9

我看到这个问题出现了很多,并写了一些关于在这里切换Views/UserControls的东西.通常我使用a ContentControlContentTemplate基于a 切换出来DataTrigger,但是相同的主要工作来切换TabControlItemTemplate

<DataTemplate x:Key="LoggedOutTemplate">
     <local:UnloggedView />
</DataTemplate> 

<DataTemplate x:Key="LoggedInTemplate">
     <local:LoggedView />
 </DataTemplate>

 <TabControl>
     <TabControl.Style>
         <Style TargetType="{x:Type TabControl}">
             <Setter Property="ItemTemplate" Value="{StaticResource LoggedOutTemplate}" />
             <Style.Triggers>
                 <DataTrigger Binding="{Binding IsLoggedIn}" Value="True">
                     <Setter Property="ItemTemplate" Value="{StaticResource LoggedInTemplate}" />
                 </DataTrigger>
             </Style.Triggers>
         </Style>
     </TabControl.Style>
 </TabControl>
Run Code Online (Sandbox Code Playgroud)

您可能必须使用ElementNameRelativeSource在DataTrigger绑定中查找IsLoggedIn您的属性DataContext

至于从Logged Out视图中触发Login Command,有多种方法可以执行此操作.

我首选的方法是使用某种消息传递系统,如MVVM Light的Messenger或Microsoft Prism的EventAggregator,并ShowLoginDialog在单击按钮时触发某种消息,然后让ViewModel负责显示登录对话框订阅接收那些消息并处理它们.

另一种方法是使用RelativeSource绑定来查找Visual Tree中具有LoginCommandinIn的DataContext的对象,并绑定到该对象.

你可以在这里看到两个例子