本文介绍了根据状态在视图之间切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个显示用户好友列表的应用程序.好友列表显示为 TabItem.用户必须先登录服务器,才能获得好友列表.

Say I've an application that displays user friends list. The friends list is displayed in as a TabItem. The user has to Log in first to the server, in order to get the list of friends.

我创建了两个用户控件,一个用于用户登录时,另一个用于用户未登录时.仅此一行:

I've created two user controls, one for when the user is logged in, the the other when he is unlogged. something alone this line:

UnloggedView.xaml

UnloggedView.xaml

<UserControl x:Class="UnloggedView" ...>
    <TextBlock ...>You need to <Hyperlink Command="{Binding LoginCmd}">
        Login</Hyperlink>too see your friends list</TextBlock>
</UserControl>

LoggedView.xaml:

LoggedView.xaml:

<UserControl x:Class="LoggedView" ...>
    ...
    <ListView ItemSource={Binding Path=friends}">...
</UserControl>

主窗口有如下代码:

....
<TabItem Header="Friends">
    <vw:UnloggedView />
</TabItem>

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

I believe everything is according to the MVVM principal. The LoginCmd is a simplified variation of the DelegateCommand (from prism), implemented in the ViewModel. Both Views works fine, and as the list is populated (asynchronously), notification are fired and the View is updated. I'm happy.

所以我有两个问题:第一个问题是如何触发 LoginWindow(提示用户输入他的凭据的地方?现在,我只是创建 LoginWindow(一个视图对象)并用 ShowDialog 呈现它.它似乎我在这里通过直接从 ViewModel 操作 UI 违反了 MVVM 的规则.

So I've two questions: First question is how to I fire the LoginWindow (where the user is prompted to enter his credentials? For now, I simply create the LoginWindow (a view object) and presents it with ShowDialog. It appears like I'm breaking the rules of MVVM here by directly manipulating the UI from the ViewModel.

主要问题是在我登录服务器后,将 TabItem 的内容替换为 LoggedView 的正确方法是什么.根据 MVVM 原则,ViewModel 不应了解 View 的内部结构.我在 ViewModel 中公开 IsLogged 属性(这将触发 PropertyChanged 通知)但是我应该绑定什么才能使一切发生?我真的不希望 ViewModel 操纵视图.

main question is after I log-in with the server, what is the correct way to replace the content of the TabItem with the LoggedView. According to the MVVM principals, the ViewModel shouldn't not have knowledge to the internals of the View. I expose IsLogged property in the ViewModel (which will fire PropertyChanged notification) but what should I bind to what in order to make everything happens? I really don't want the ViewModel manipulating the View.

谢谢

推荐答案

我看到这个问题出现了很多,并且写了一些关于 在此处在视图/用户控件之间切换.通常我使用 ContentControl 并基于 DataTrigger 切换出 ContentTemplate,但是相同的原理可以切换 TabControl 的 ItemTemplate

I see this question come up a lot, and have written something about switching between Views/UserControls here. Usually I use a ContentControl and switch out the ContentTemplate based on a DataTrigger, however the same principal works to switch a TabControl's ItemTemplate

<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>

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

You may have to use ElementName or RelativeSource in your DataTrigger binding to find the IsLoggedIn property in your DataContext

至于从注销"视图中触发登录命令,有多种实现方式.

As for firing a Login Command from your Logged Out view, there are multiple ways of doing it.

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

My preferred method is to use some kind of messaging system such as MVVM Light's Messenger, or Microsoft Prism's EventAggregator, and firing some kind of ShowLoginDialog message when the button is clicked, then let whatever ViewModel is taking care of showing the login dialog subscribe to receive those messages and handle them.

另一种方法是简单地使用 RelativeSource 绑定来查找可视化树中在其 DataContext 中具有 LoginCommand 的对象,并绑定到该对象.

Another way is simply use a RelativeSource binding to find the object in the Visual Tree that has the LoginCommand in it's DataContext, and bind to that.

您可以在此处

这篇关于根据状态在视图之间切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 04:21