WPF MVVM导航技术

时间:2014-09-18 16:19:44

标签: c# wpf xaml mvvm

我知道有很多关于WPF导航的问题,对于使用MVVM模式开发的应用程序,我已经阅读了数十个答案,但我可能遗漏了一些东西。 我开始根据Rachel的文章here构建一个应用程序。一切正常,这个XAML有一个 ApplicationView 窗口:

<Window x:Class="CashFlow.ApplicationView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:CashFlow.ViewModels"
    xmlns:v="clr-namespace:CashFlow.Views"
    Title="ApplicationView" Height="350" Width="600" WindowStartupLocation="CenterScreen">


<Window.Resources>
    <!--Here the associations between ViewModels and Views-->
    <DataTemplate DataType="{x:Type vm:HomeViewModel}">
        <v:HomeView />
    </DataTemplate>
</Window.Resources>

<!--Define here the application UI structure-->
<DockPanel>
    <Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
        <ItemsControl ItemsSource="{Binding PageViewModels}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding Name}"
                            Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                            CommandParameter="{Binding}"
                            Margin="2,5" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>            
    </Border>

    <ContentControl Content="{Binding CurrentPageViewModel}" />

</DockPanel>

ApplicationViewModel ,在应用程序启动时为此窗口设置为 DataContext ,维护我的ViewModel的 ObservableCollection 。借助数据模板,可以使用 ContentControl 来渲染视图,从而将每个视图与其视图模型相关联。在这种情况下导航是通过&#34;侧栏&#34;按钮,绑定到执行 CurrentPageViewModel 对象更改的 ApplicationViewModel 命令。 我想知道如果没有按钮的侧边栏我可以执行导航。只有 Content 控件,我应该能够从其他viewmodel更改 CurrentPageViewModel 吗?可能答案非常简单,但我现在无法看到。

2 个答案:

答案 0 :(得分:1)

您的顶级homeview模型可以通过eventbus模式编排导航。要使用eventbus,您将注入一个跟踪想要通知事件的对象的对象。然后,当视图模型引发事件时,homeviewmodel会接收它并执行currentpageviewmodel分配,该分配将导航到下一个视图模型。

例如:

Messenger定义了两种方法 - RegisterForEvent<IEvent>(ViewModel aViewModel)RaiseEvent(IEvent event)

所以你要定义一个订阅事件的函数 -

HomeViewModel.cs

...
void SubscribeForEvents() {
    Messenger.RegisterForEvent<NavigationEvent>(this);
}

然后将Messenger注入其他视图模型,并从这些视图模型中引发事件:

Messenger.RaiseEvent(new NavigationEvent { TargetViewModel = new TargetViewModel() });

事件类似于

public class NavigationEvent : IEvent {
    ViewModel TargetViewModel { get;set;}
}

答案 1 :(得分:0)

C鲍尔对你所缺少的是正确的。我发现为了切换数据上下文,你需要一个信使服务来标记你的“applicationviewmodel”来切换它的数据上下文。在讨论中here详细讨论了您需要的步骤。

在applicationviewmodel中注册要接收的消息,然后在接收消息功能中处理数据上下文切换。

此外,这可能是真的,但我不得不使用1个窗口,如果我想要始终显示1个窗口,则使用多个用户控件而不是多个窗口。最后,我跟着Sheridan's example并在我的app.xaml中定义了我的数据模板,而不是窗口本身。