c# – 如何在WPF中懒洋洋地创建UI元素?

前端之家收集整理的这篇文章主要介绍了c# – 如何在WPF中懒洋洋地创建UI元素?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们正在创建一个 WPF应用程序,它大量使用高度装饰的输入元素.装饰元素的一个简单示例是TextBox,当它没有焦点时看起来像只读TextBlock,并在接收焦点后变成TextBox.此外,当更改的值保存到数据库时,会提供其他可视反馈.问题是显示包含大量这些元素的视图(假设为100)非常慢并且使应用程序非常无响应.

我们已将此装饰器实现为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). (实际上这些元素甚至有更多与验证和其他特定要求相关的状态,但你肯定得到了元素真正高度装饰的观点.)

解决方法

而不是预先绘制所有UI元素,只绘制所需的元素

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”设置为测试,以查看是否修复了加载时间.

如果确实如此,并且您不想使用模板路径,则可以确保将所有对象的可见性设置为“开始折叠”,并且只有在应该显示时才将它们设置为“可见”.

如果它不能解决您的加载时间,那么您的问题可能就在其他地方.例如,它看起来像你的一些装饰物品是根据放在它里面的内容控制大小,因此它可能什么实际影响速度不显示对象,但确定对象的大小.

猜你在找的C#相关文章