我们正在创建一个大量使用高度装饰的输入元素的WPF应用程序。装饰元素的一个简单示例是TextBox,它在没有焦点时看起来像只读TextBlock,并在接收焦点后变为TextBox。另外,当更改的值被保存到数据库时会提供额外的视觉反馈。问题是,显示一个包含很多这些元素的视图(比方说100)非常慢,并且使应用程序非常无响应。如何在WPF中懒洋洋地创建UI元素?
我们已经实现了这个装饰器作为用户控件,它包含所有必需的元素(例如TextBlock显示未聚焦的文本和旋转图像忙标志)。然后,我们将输入元素添加为此装饰器控件的子元素,这意味着除了所有额外的元素之外,装饰器还在其可视化树中包含输入元素。在XAML,这将是这样的:
<custom:Decorator Context="{Binding ValueHelper}" >
<TextBox Text="{Binding ValueHelper.Text}"/>
</custom:Decorator>
这很容易让我们来装点我们想要的任何输入元素,无论是任何一个文本框中,日期选择器,组合框或任何自定义元素。
现在回到问题:比方说,我们有一个视图,其中包含100个装饰文本框,我们导航到该视图。怎么了?至少我的四核笔记本电脑冻结很长一段时间,因为它必须创建许多文本块,矩形,图像等,以提供每个装饰元素的视觉反馈,尽管没有装饰品可见但。真正需要的仅仅是100个TextBlocks,因为这是屏幕上可见的。只有在元素接收到鼠标悬停事件后,或者在需要其他元素时才关注。而且,一次只能编辑一个元素,因此只有一个输入元素(在这种情况下是文本框)对于整个应用程序就足够了。
那么,如何在不为视图中的每个元素创建所有装饰元素(或实际输入元素)的情况下实现相同装饰的最佳方式是什么?
装饰文本框,以澄清使用情况的一个例子:
文本框时像没有焦点或鼠标光标,只读TextBlock的目前并未在它的上面(状态1)。此外,还显示了三个点(“...”),因为元素不会有任何价值。
当鼠标光标移动到元素的顶部时,TextBlock周围出现一个绿色的虚线矩形,表示该元素可以被修改(状态2)。如果TextBox碰巧是只读的,颜色将会变成红色。
接收聚焦元件后变成可用于修改的实际值(状态3)实际文本框。
文本框失去它的焦点之后,并表明,该值正在被保存忙指示符显得元件(状态4)的左边的值存储到数据库中。
最后,该值已被保存和元件返回到表示新的值(状态5)它的空闲状态。 (实际上这些元素有更多的状态与验证和其他特定要求有关,但是您肯定知道元素真的是高度装饰的。)
谢谢!控件模板绝对是装饰元素的方式。但是,这并不能解决实际输入元素的问题。 TextBox是我们最轻的元素,我们有更重的自定义输入元素(例如日期选择器),我们无法创建。我们已经设置了可见性来折叠,但仍然会创建可视化树,并加载所有相关资源,这会导致严重的性能问题。 – user544511 2013-03-28 08:04:43
@ user544511当你说“所有相关资源被加载”时,你的意思是每个装饰器都被加载了吗?因为如果你使用的装饰一个UI控制和换出的模板,因为只有一个元素在视觉树同时 – Rachel 2013-03-28 11:52:10
对不起,我正在度假,不能刚才的答复存在,你不应该让这种行为。我的意思是创建了实际的输入元素(这是装饰器的子元素,例如日期选取器或文本框),它的所有资源(包括子元素)都被加载并添加到可视树中(即使它已折叠)。这导致巨大的性能下降,因为日期选择器的元素比例如重量要大得多。一个文本框。 – user544511 2013-04-02 11:08:57