0

我正在定义一种策略,其中主视图将使用数据模板在视图之间切换。目前它可以在 3 个视图之间切换:

  • ApplicationView:它实际上是由许多不同的视图组成的视图,主要使用选项卡/停靠进行分层。这是一个处理应用程序数据的视图。
  • LogInView:用于登录用户。
  • DialogView:用于显示对话框视图。此视图还将使用数据模板来选择所需的适当视图。

这个想法是,当需要显示对话框视图时,将其设置为主视图上的当前视图。选择完成后,此信息将传递给 ApplicationView,或作为 ApplicationView 一部分的视图。虽然显示了 DialogView,但 ApplicationView 不能从内存中释放,因为 ApplicationViewModel 仍将处理数据(它需要在后台不断工作)。

我正在考虑使用 DataTemplates 来实现这一点,并将 ContentControl 的内容绑定到 CurrentView:

// in MainView
DataTemplate DataType="{x:Type vm:ApplicationViewModel}">
    <vw:ApplicationView />
</DataTemplate>

.....

// in MainViewModel
public ViewModelBase CurrentView { get; set; }

基本上我试图避免对对话框使用模态窗口。

1)这个策略可以吗,还是有一些我不知道的问题?

2) 当我切换到 DialogView(我实际上是在切换视图模型)时,ApplicationView/ApplicationViewModel 会发生什么?我是否需要将 ApplicationViewModel 的引用存储在某处,这样它就不会被垃圾收集?我没有对此进行测试,但可能当我设置 CurrentView 时,将创建一个新的 ViewModel/View 实例。

3)连接到第二个问题,当使用DataTemplates时,以前使用的View/ViewModel会发生什么,现在被不同的view/viewmodel替换了?

4

2 回答 2

0

就个人而言,我会发现在标准网格中使用 ZOrdering 更容易,并将所有内容放在同一个视图中 - 使用 ViewModel 来管理可见性。

例如

<Grid>
    <Grid Visibility="{Binding IsView1Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 1 contents -->
    </Grid>
    <Grid Visibility="{Binding IsView2Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 2 contents -->
    </Grid>
    <Grid Visibility="{Binding IsView3Visible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- view 3 contents -->
    </Grid>
    <Grid Visibility="{Binding IsDialogVisible, 
        Converter={StaticResource BoolToVisibilityConverter}}">
        <!-- dialog contents contents -->
    </Grid>
</Grid>
于 2012-06-21T13:19:15.403 回答
0
  1. 我认为您切换视图的方式没有任何问题,尽管通常您不想在显示对话框时摆脱应用程序。

    我过去所做的是将CurrentView, 和DialogViewin aGrid放在彼此的顶部,然后ApplicationViewModel包含一个IDialogViewModelIsDialogVisible属性,当您想要显示对话框时,只需填充这两个字段。(请参见下面的示例)

  2. ApplicationViewModel如果您想回到某个地方并避免创建新的,则必须将其存储在某个地方ApplicationViewModel

  3. WPF 处理不再可见的 UI 对象,因此将CurrentViewfrom切换LoginApplication将摆脱LoginView并创建一个ApplicationView

    ContentControl 的 Content 被设置为您的ViewModel,因此 ViewModel 实际上被放入应用程序中VisualTree。每当 WPF 在其中遇到一个VisualTree它不知道如何绘制的对象时,它将使用TextBlock包含.ToString()该对象的 来绘制它。通过定义 a DataTemplate,您是在告诉 WPF 如何绘制对象而不是使用其默认.ToString()方法。一旦对象离开VisualTree,为渲染对象而创建的任何视觉对象都将被销毁。

虽然我会继续使用您目前拥有的切换视图,但我不会将这种方法用于LoginApplicationDialog视图。

通常,LoginView登录时应该只显示一次,尽管Dialog如果您允许用户在登录后切换登录名,它可能会再次显示。因此,我通常LoginView在启动代码中显示 ,然后显示ApplicationView一次登录成功.

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    var login = new LoginDialog();
    var loginVm = new LoginViewModel();

    login.DataContext = loginVm;
    login.ShowDialog();

    if (!login.DialogResult.GetValueOrDefault())
    {
        Environment.Exit(0);
    }

    // Providing we have a successful login, startup application
    var app = new ApplicationView();
    var context = new ApplicationViewModel(loginVm.CurrentUser);
    app.DataContext = context;
    app.Show();
}

就像我之前说的,我不想在Application显示时隐藏 a Dialog,所以我会制作 the 的Dialog一部分Application

DataTemplate这是我将用于我的 Dialog的示例ApplicationViewModel,使用我自己的博客中的自定义弹出窗口作为对话框

<Grid x:Name="ApplicationView">
    <ContentControl Content="{Binding CurrentView}" />
    <local:PopupPanel x:Name="DialogPopup"
                      Content="{Binding DialogContent}"
                      local:PopupPanel.IsPopupVisible="{Binding IsDialogVisible}"
                      local:PopupPanel.PopupParent="{Binding ElementName=ApplicationView}" />
</Grid>
于 2012-06-21T13:27:16.110 回答