19

以下哪些 TextBlocks 的绑定会消耗更多性能:

<Window  
  x:Name="Me"
  x:Class="MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:src="clr-namespace:WpfApplication1" 
  Title="MainWindow">
  <StackPanel>
    <TextBlock Text="{Binding Title, ElementName=Me}"/>
    <TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType={x:Type src:MainWindow}}}"/>
  </StackPanel>    
</Window>

我确信当 TextBlocks 处于具有许多兄弟姐妹和祖先的高嵌套级别时,我的问题可能会有所不同。

注意事项

(仅基于个人想法,我可能在每个特定的地方都错了!):

  • ElementName

    • 可能会搜索并比较当前元素以进行更多控制,通过它的所有孩子、兄弟姐妹、叔叔和叔叔,包括祖先(也许有一个所有注册名称的哈希表?)
    • 获取Name控件的属性应该比调用更少的性能GetType
    • 比较字符串比比较类型便宜,尤其是当您知道大多数控件甚至没有Name设置时。
  • FindAncestor

    • 只会遍历祖先,而不是兄弟姐妹“叔叔”、“堂兄弟”等。
    • 最有可能用于GetType确定祖先类型;GetType 比简单的属性 getter 花费更多的性能Name(也许 DP 不同?)
4

3 回答 3

31

通过争论你认为哪个会更快来尝试回答这类问题通常是一个糟糕的主意。最好构建一个实验来测量它。

我稍微修改了您的设置 - 我将相关的 Xaml 放入 UserControl 中,并绑定到该Name属性,因为UserControl没有Title属性。然后我编写了一些代码来创建控件的新实例并将其添加到 UI,并使用Stopwatch来测量构建和加载它所花费的时间。(我在构建用户控件之前开始计时,并在用户控件引发其Loaded事件后停止。)

DispatcherTimer我每秒运行20 次此代码,因此我可以进行大量测量,以期减少实验误差。为了尽量减少由于调试和诊断代码造成的失真,我在 Release 版本中运行,我只在 2000 次迭代完成后计算和打印平均值。

经过 2000 次迭代后,该ElementName方法平均为 887us。

经过 2000 次迭代后,该RelativeSource方法平均为 959us。

因此ElementName,在这个特定的实验中,比RelativeSource. 在只有一个命名元素的情况下加载一个UserControl只有一个Grid和一个的琐碎,该方法看起来需要 92% 的时间来加载该方法所花费的时间。TextBlockElementNameRelativeSource

当然,我在这里测量一个小的人工示例。ElementName 方法的性能可能会根据范围内命名元素的数量而有所不同。并且可能还有其他意想不到的因素可能会在实际场景中产生完全不同的结果。因此,如果您想获得更好的图像,我建议您在实际应用程序的上下文中执行类似的测量。

我用 10 个 TextBlocks 而不是 1 个重复了实验。ElementName然后平均 2020us,而该RelativeSource方法平均为 2073us,两次测试的迭代次数再次超过 2000 次。奇怪的是,这里有一个较小的差异,不仅是相对而言,而是在绝对方面——单元素示例显示出 72us 的差异,而十元素示例显示出 53us 的差异。

我开始怀疑我在我的主机上运行我的测试会导致更多的可变性,而不是仔细配置尽可能少的东西以尽量减少噪音。

另一种变化:仍然有 10 个绑定文本块,我向用户控件添加了另外 10 个空的、未绑定的命名文本块。这里的想法是引入更多命名事物 -ElementName现在必须在 11 个命名事物中找到一个命名项目。现在的平均值ElementName是 2775us。这些额外的 10 个命名元素的RelativeSource方法出现在 3041us。

RelativeSource再次,我怀疑我的台式机在这里的可变性 -在这里表现得比在本应更ElementName有利的场景中表现得更差似乎很奇怪。

无论如何,看起来相当清楚的是,这里的加载成本对元素的数量比对您使用的绑定样式更敏感。显然有一个小优势,ElementName但足够小(并且结果足够奇怪)来怀疑得出结论一定更快的有效性。

所以我们可以构建更仔细的实验​​来获得更好的画面。但在我看来,如果你不能最终证明在普通计算机上运行时性能上有显着差异,那么争论哪个更快基本上是浪费时间。

所以总而言之:性能是错误的关注点。选择更易读的代码。

于 2010-12-01T12:57:31.937 回答
4

两者中的后者需要遍历可视化树以寻找特定的祖先类型,而先验直接查看窗口的名称范围以查找具有该名称的已注册对象......我的猜测是后者稍微慢一些......也就是说,我认为不会有显着的性能差异。

希望能帮助到你,

Aj

于 2010-11-30T19:48:09.127 回答
1

一般来说,ElementName应该尽可能使用。

给定的示例和基准示例非常简单。在现实世界的示例中,元素具有更大的可视化树,并且FindAncestor绑定必须遍历更多元素才能找到该元素。

FindAncestor通过将一些绑定更改ElementName为真实世界应用程序中的绑定,我获得了 SECONDS 。

恕我直言,ElementName绑定也更具可读性。

于 2020-09-23T09:05:58.730 回答