【问题标题】:Should I be using UserControls for my Views instead of DataTemplates?我应该为我的视图使用 UserControls 而不是 DataTemplates 吗?
【发布时间】:2011-05-26 11:50:50
【问题描述】:

我正在阅读this post,作者建议使用 DataTemplates 定义 ViewModel 是一种疯狂的做法(#7)。我经常这样,真的有那么糟糕吗?

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <Grid>
        ...
    </Grid>
</DataTemplate>

我的大多数视图只是一个定义一个或两个 DataTemplate 的 ResourceDictionary。对我来说,这样做比为每个 ViewModel 创建一个 UserControl 更有意义。为什么不需要 WPF 的可视化树中的额外层?当 DataTemplate 为我执行此操作时,我为什么要处理将 ViewModels 映射到 Views 的问题?这种语法真的是“疯子方法”吗?

【问题讨论】:

  • 我在 Visual Studio 中工作,据我所知,您无法获得对 DataTemplates 的设计器支持。对于重要的视图,我喜欢在修改 XAML 时查看它的外观。但我不知道它在 Blend 中是如何工作的。
  • @default.kramer 是的,我忘记了。我几乎从不使用 VS 的 XAML 设计器,因为它很慢、很慢,而且一半时间都不能工作。如果我确实想用它来设计 DataTemplate,我通常会创建一个新的 UserControl,按照我想要的方式进行设计,然后将内容复制/粘贴到 DataTemplate 中。

标签: wpf mvvm user-controls view datatemplate


【解决方案1】:

这没什么不好,除了非常大的 xaml 文件和缺乏 DataTemplates 在设计表面上的编辑支持。

如果这些问题正在伤害您,您可以随时...

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <local:MyViewModelUserControl />
</DataTemplate>

【讨论】:

  • 正如我在回复 Souvik 的帖子时提到的,我通常为每个视图创建一个单独的 ResourceDictionary,并在运行时将它们全部合并。这使我的 xaml 文件大小合理。我可以理解设计师缺乏编辑支持,尽管我讨厌那个东西并且几乎从不使用它(当我发布问题时我实际上已经忘记了它)。我发现没有它编码要快得多。
  • 我也使用了 Will 建议的解决方案。我发现它是一个优雅的解决方案。当您有复杂的屏幕电影时,您可以将其分解为多个子视图/视图模型,并且您当然会受益于视觉设计师,因为整个视图的每个部分只是其他较小的视图。
  • @Rachel:它确实有其(授予的、有限的)好处。特别是在尝试正确排列所有内容时。我的数据模板中似乎总是有一个Expander,我不能简单地单击它来公开其内容以进行设计工作...
【解决方案2】:

DataTemplate 的好处是它们被强类型化为 Viewmodel 类。您需要做的就是在 View 中创建一个 ContentPresenter 并将 DataContext 绑定到 VM。如果您的 DataTemplate 在 ResourceDictionary 中定义并且具有 DataType 属性而不是 Key,则 WPF 将在内部为 VM 类找出正确的 DataTemplate 并显示它。

但正如您所提到的,我们无法在单独的文件中创建 DataTemplate。因此,ResourceDictionary 中存在 DataTemplates 的文件(例如 App.xaml),文件变得非常混乱,很快就很难管理代码。

所以我的看法是,如果 VM 很简单,请创建一个 DataTemplate。否则,最好创建一个单独的 UserControl 并将其内容绑定到 VM。

【讨论】:

  • 实际上每个 DataTemplate 都有自己的 .xaml 文件,这些文件在运行时添加到 App.Current.MainWindow.Resources.MergedDictionaries。这使 ResourceDictionary 文件小而易于管理。
  • 好的,我从未尝试将 DataTemplates 放在单独的文件中。这应该注意保持 ResourceDictionary 文件的清洁。我面临的另一个问题是,并非所有控件都支持可以绑定到 VM 的 ICommand。例如如果我必须在 TextBlock 上处理 MouseDown,我会在 UserControl 后面的代码中创建一个事件处理程序,然后从那里调用 VM 中的适当命令。有没有更简洁的方法从 DataTemplate 调用 VM 中的命令?
  • 我使用这里的代码:marlongrech.wordpress.com/2008/12/04/… 它允许您将命令附加到任何事件,例如MouseDown 或SelectionChanged。此外,如果您为 ResourceDictionary 提供一个 x:Class 属性并添加一个与您的 ResourceDictionary 名称相同且具有 .cs 扩展名 (MyResourceDictionary.xaml.cs) 的新类,它将为其创建一个代码隐藏文件。跨度>
【解决方案3】:

我遇到了性能问题。接下来两种情况有区别:

1.

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <!-- xaml is moved to separate user control -->
    <local:MyViewModelUserControl />
</DataTemplate>

2.

<DataTemplate DataType="{x:Type local:MyViewModel}">
    <!-- xaml is typed here directly -->
    <Border>
         ...
    </Border>
</DataTemplate>

在第一种情况下,渲染结果的时间比在第二种情况下要长。而这种差异大约是 2 倍。 我将其发布为单独的question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-04
    • 2023-03-15
    • 2011-03-02
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    相关资源
    最近更新 更多