使用数据模板时view / viewmodel的生命周期

时间:2012-06-21 11:48:39

标签: wpf mvvm

我正在定义一个策略,主视图将使用数据模板在视图之间切换。目前它可以在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替换?

2 个答案:

答案 0 :(得分:0)

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

E.g

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

答案 1 :(得分:0)

  1. 我没有看到您切换视图的方式有任何问题,尽管通常您不希望在显示对话框时摆脱应用程序。

    我过去所做的是将CurrentViewDialogView放在Grid中,以便它们彼此重叠,然后拥有{ {1}}包含ApplicationViewModelIDialogViewModel属性,当您想要显示对话框时,只需填充这两个字段即可。 (见下面的例子)

  2. 如果您想要返回IsDialogVisible并避免创建新的ApplicationViewModel

  3. ,则必须将ApplicationViewModel存储在某处
  4. WPF处理不再可见的UI对象,因此将CurrentViewLogin切换为Application将摆脱LoginView并创建ApplicationView

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

  5. 虽然我会继续使用您目前用于切换视图的内容,但我不会对VisualTreeLoginApplication视图使用该方法。

    通常情况下,Dialog只应在登录时显示一次,但如果您允许用户在登录后切换登录,它可能会再次显示在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,所以我会将Dialog <{1}} < / p>

    以下是我将Dialog用于Application的示例,使用我自己的custom Popup from my blog作为对话

    DataTemplate