我们已将此装饰器实现为UserControl,其中包含所有必需元素(例如,TextBlock用于显示未聚焦文本和旋转图像用于忙碌指示符).然后我们将input元素添加为此装饰器控件的子元素,这意味着除了所有额外元素之外,装饰器还在其可视树中包含input元素.在XAML中,这看起来像:
<custom:Decorator Context="{Binding ValueHelper}" > <TextBox Text="{Binding ValueHelper.Text}"/> </custom:Decorator>
这使我们可以轻松地装饰我们想要的任何输入元素,无论是文本框,日期选择器,组合框还是任何自定义元素.
现在回到问题:假设我们有一个包含100个装饰文本框的视图,我们导航到该视图.怎么了?至少我的四核笔记本电脑冻结了很长时间,因为它必须创建数百个文本块,矩形,图像等,以便为每个装饰元素提供视觉反馈,尽管还没有可见的装饰.真正需要的只有100个TextBlocks,因为这是屏幕上可见的内容.仅在元素接收鼠标悬停事件或焦点时才需要其他元素.此外,一次只编辑一个元素,因此只有一个输入元素(在本例中为文本框)足以满足整个应用程序的需要.
那么,如果不为视图中的每个元素创建所有装饰元素(或实际的输入元素),那么实现相同装饰的最佳方法是什么?
用于阐明用例的装饰TextBox的示例:
当文本框没有焦点或鼠标光标当前不在其上时,文本框看起来像只读TextBlock(状态1).此外,示出了三个点(“……”),因为元素当前不具有任何值.
当鼠标光标移动到元素顶部时,TextBlock周围会出现一个带绿色的虚线矩形,表示该元素可以被修改(状态2).如果TextBox恰好是只读的,颜色将为红色.
接收到焦点元素后,变成实际的TextBox,可用于修改实际值(状态3).
在文本框失去焦点后,该值将存储到数据库中,并且为了显示当前正在保存该值,繁忙的指示符出现在元素的左侧(状态4).
最后,该值已被保存,元素返回到显示新值的空闲状态(状态5). (实际上这些元素甚至有更多与验证和其他特定要求相关的状态,但你肯定得到了元素真正高度装饰的观点.)
解决方法
WPF允许您使用DataTrigger修改对象的模板,因此您可以根据触发器调整Decorator的模板
Decorator的示例样式可能如下所示:
<Style TargetType="{x:Type ContentControl}"> <!-- Default Template --> <Setter Property="ContentTemplate" Value="{StaticResource NoDecoratorTemplate}" /> <Style.Triggers> <DataTrigger Property="Text" Value=""> <Setter Property="ContentTemplate" Value="{StaticResource BlankTemplate}" /> </DataTrigger> <Trigger Property="IsMouSEOver" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource MouSEOverTemplate}" /> </Trigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource FocusedTemplate}" /> </Trigger> <DataTrigger Property="{Binding IsLoading}" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource LoadingTemplate}" /> </DataTrigger> </Style.Triggers> </Style>
此外,WPF不应加载不可见的项目.您可以尝试将装饰器Visibility =“Collapsed”设置为测试,以查看是否修复了加载时间.
如果确实如此,并且您不想使用模板路径,则可以确保将所有对象的可见性设置为“开始折叠”,并且只有在应该显示时才将它们设置为“可见”.
如果它不能解决您的加载时间,那么您的问题可能就在其他地方.例如,它看起来像你的一些装饰物品是根据放在它里面的内容控制大小,因此它可能什么实际影响速度不显示对象,但确定对象的大小.