我应该使用UserControls来代替DataTemplates作为我的视图吗?

12

我在阅读这篇文章,作者提出使用DataTemplates定义一个ViewModel是疯子的做法(#7)。我经常这样做,这真的很糟糕吗?

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

我的大多数视图都是简单的ResourceDictionary,定义了一个或两个DataTemplate。 对我来说,这比为每个ViewModel创建一个UserControl要更有意义。 如果不需要WPF视觉树中的额外层,则为什么要这样做? 如果一个DataTemplate可以帮我处理ViewModel到View的映射,为什么还要自己去做呢? 这种语法真的是“狂人的方法”吗?


我在使用Visual Studio,就我所知,DataTemplates无法获得设计师支持。对于复杂视图,我喜欢在修改XAML时看到它的外观。但是我不清楚在Blend中的工作方式如何。 - default.kramer
1
@default.kramer 这是真的,我忘记了。我几乎从不使用VS的XAML设计师,因为它很卡顿、慢,并且有一半的时间都无法正常工作。如果我确实想要使用它来设计DataTemplate,我通常会创建一个新的UserControl,按照自己的意愿进行设计,然后将其内容复制/粘贴到DataTemplate中。 - Rachel
3个回答

7

除了XAML文件过大和数据模板在设计界面上缺乏编辑支持之外,这方面没有什么不好的。

如果这些问题困扰着您,您可以随时...

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

正如我在回复Souvik的帖子中提到的,我通常为每个视图创建一个单独的ResourceDictionary,并在运行时将它们合并。这样可以使我的xaml文件大小合理。我可以理解设计师缺乏编辑支持,尽管我讨厌那个东西,几乎从不使用它(实际上,在我发帖时我都忘了它的存在)。我发现在没有它的情况下编码速度更快。 - Rachel
2
我也使用了Will建议的解决方案。我发现这是一个优雅的解决方案。当你有复杂的屏幕动画时,你可以将其分解为多个子视图/视图模型,并且当然你仍然可以从可视化设计师中受益,因为整个视图的每个部分都只是其他更小的视图。 - Bruno
2
@Rachel:它确实有其(尽管有限)的好处。特别是在尝试正确地排列所有内容时。我总是会在我的数据模板中有一个“Expander”,无法简单地单击以显示其内容进行设计工作... - user1228

1
DataTemplate 的好处是它们被强类型到 Viewmodel 类。您所需要做的就是在 View 中创建一个 ContentPresenter 并将 DataContext 绑定到 VM。如果您的 DataTemplate 是在 ResourceDictionary 中定义且具有 DataType 属性而不是 Key,则 WPF 将在内部找出正确的 DataTemplate,以显示 VM 类。
但正如您所提到的,我们无法在单独的文件中创建 DataTemplate。因此,存储 DataTemplates 的文件(例如 App.xaml)中,该文件变得非常混乱,并且很快变得难以管理。
因此,我的建议是,如果 VM 简单,则创建 DataTemplate。否则最好创建一个单独的 UserControl,并将其内容绑定到 VM。

1
实际上,每个数据模板都有自己的 .xaml 文件,并且这些文件会在运行时添加到“App.Current.MainWindow.Resources.MergedDictionaries”中。这使得资源字典文件变得小而易于管理。 - Rachel
好的,我从未尝试将DataTemplates放在单独的文件中。这应该可以解决保持ResourceDictionary文件干净的问题。我遇到的另一个问题是,并非所有控件都支持可以绑定到VM的ICommand。例如,如果我必须处理TextBlock上的MouseDown事件,则在UserControl的代码后台中创建一个事件处理程序,然后从那里调用VM中的适当命令。有没有更简洁的方法从DataTemplate中调用VM中的命令? - Souvik Basu
1
我使用在这里找到的代码:http://marlongrech.wordpress.com/2008/12/04/attachedcommandbehavior-aka-acb/ 它允许您将命令附加到任何事件,例如 MouseDownSelectionChanged。此外,如果您给 ResourceDictionary 添加一个 x:Class 属性,并添加一个与 ResourceDictionary 同名的新类并以 .cs 扩展名命名(MyResourceDictionary.xaml.cs),它将为其创建一个代码后台文件。 - Rachel

0
我在编程方面遇到了性能问题。以下两种情况存在差异:
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>

在第一种情况下,呈现结果所需的时间比第二种情况要长。这种差异大约是两倍。 我将其发布为单独的问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接