为什么在DataTemplate中使用UserControl比直接使用XAML更慢?

3

我有这样的代码:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyViewModel}">

           <!-- xaml is typed here directly -->
           <Border>
               ...
           </Border>

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

而DataTemplate中的XAML代码很长(超过200行)。

我想把DataTemplate中的XAML代码移到单独的UserControl中,以便更容易地编辑和维护。我采取以下步骤:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyViewModel}">

            <!-- xaml is moved to separate UserControl -->
            <local:MyViewModelUserControl />

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我遇到的问题是第二段代码(使用UserControl)的渲染/处理时间比第一段代码长两倍左右。有什么办法可以解决吗?
注意:我移动的不是ListBox,而是DataTemplate中的XAML。原因不是为了重用此代码,而是为了最小化放置ListBox的主文件。另一个问题是,我在ListBox中有几个DataTemplate(针对几个ViewModel),而且XAML非常庞大。这就是为什么我想将DataTemplate中的XAML(位于其中的)移动到单独的控件中的原因。
3个回答

4

我知道这是一个老问题,但最近我也遇到了这个问题。在WPF中创建用户控件存在很大的开销,这似乎来自于将代码后台类文件连接到XAML。如果你只是想将XAML移动到另一个位置,只需在另一个文件的ResourceDictionary中定义你的DataTemplate,并将其作为StaticResource加载。这将提供一些优势:

(1) 可以使用x:Name对元素进行命名,而这在内联DataTemplate中是不允许的。

(2) 性能更好。直接使用XAML的DataTemplateDataTemplate中的UserControl快得多。

(3) 更加清晰。你可以将DataTemplate定义在任何地方(同一文件中的资源字典、你正在使用它的附近、不同的文件等),并将其作为StaticResource引用。


1
在我看来,如果你只在一个地方使用此ListBox,则目前没有必要将其分离为单独的UserControl。无论如何,如果你非常关心优化代码和创建可重用控件,那么可以创建一个单独的UserControl。但是,对于可重用的用户控件,你不能有一个视图模型,因为它是基于视图的东西。
你必须将listbox的所需属性绑定到Dependency Properties,然后创建UserControl。通过这样做,你既不违反MVVM模式,又使控件可供其他人重用。
引起延迟的原因不是由于你所做的,而可能是由于数据获取时间或某些其他进程导致应用程序滞后。

我移动的不是ListBox,而是DataTemplate内部的xaml。原因不是为了重用这段代码,而是将其最小化放置在ListBox所在的主文件中。另外一件事是,我在ListBox中有几个DataTemplates(针对几个ViewModels),而且xaml非常庞大。这就是为什么我想将DataTemplate内部的xaml移动到单独的控件中。我也已经在答案中添加了这些信息。如果我没有描述清楚,请谅解。 - Sergey
但是将数据模板定义在单独的文件中并不利于更好的可维护性和可读性。一个列表将拥有它自己的数据模板或多个数据模板也没有问题。如果要创建可重用的列表控件,那就没问题了。但是将您的数据模板移到单独的文件中并不是那么好的选择。 - ViVi
我有一个用户控件,用于显示某个ViewModel中的项目,并包含该项的行为。我将此控件放置在ListBox.ItemTemplate内部。这就是您可以在问题的第二段代码中看到的内容。而且事实证明,在ListBox的ItemTemplate中使用UserControl比直接在ListBox.ItemTemplate中编写相同的xaml更慢(您可以在上面的第一段代码中看到)。这就是问题所在。 - Sergey
请发布 MyViewModelUserControl 的代码。我认为问题不是因为您将代码移动到另一个 xaml 文件中引起的。可能是数据获取或数据变得更大导致了这个问题。 - ViVi

0
你可以简化你的 "MyViewModelUserControl" - 不要继承自 UserControl,而是直接继承自 Border,并在它的 XAML 中这样做(Border 代替 UserControl 作为根元素)。这将给你与之前相同的性能,但你可以将其保留在一个单独的控件中。

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