延迟加载 XAML [英] Deferred loading of XAML

查看:30
本文介绍了延迟加载 XAML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理的一个项目有一些相当复杂的 XAML,它明显影响了视觉性能.相当多的控件在初始状态下是折叠的;然而,由于他们的 XAML 被解析并构建了可视化/逻辑树,因此显示几乎是空白的对象的速度非常慢.

A project I'm working on has some rather complex XAML that is noticeably affecting visual performance. Quite a few controls are collapsed for the initial state; however, since their XAML is parsed and visual /logical trees built, it's very slow to show what amounts to an almost blank object.

看起来(并希望在此确认)使用初始状态为 Collapsed 的 ContentControl,然后将所需控件作为该 ContentControl 的 DataTemplate 嵌入,将延迟在 DataTemplate 中加载所需控件,直到 ContentControl可见.

It looks like (and would like confirmation here) that using a ContentControl with an initial state of Collapsed and then embedding the desired control as a DataTemplate for that ContentControl, will defer loading of the desired control in the DataTemplate until the ContentControl is made visible.

我已经构建了一个通用的 DeferredContentControl 来监听主 UI 控件的 LayoutUpdated 事件(通常是我想要快速出现的任何元素),并且当该 UIElement 的第一个 LayoutUpdated 事件触发时,我使用了调度程序将 DeferredContentControl 的可见性翻转为 true,这会导致 DeferredContentControl 的 DataTemplate 中的控件实例化.当用户对屏幕的初始视图(现在速度很快)做出反应时,数据模板中的加载缓慢"(但仍处于折叠状态)控件已准备就绪.

I've built a generic DeferredContentControl that listens for the LayoutUpdated event of the main UI control (in general whatever element it is that I want to appear quickly), and when the first LayoutUpdated event of that UIElement fires, I used the Dispatcher to flip the visibility of the DeferredContentControl to true, which causes the control in the DeferredContentControl's DataTemplate to instantiate. By the time the user has reacted to the initial view of the screen (which is now fast), the "slow to load" (but still collapsed) control in the data template is ready.

这看起来是一个合理的方法吗?有什么陷阱吗?它似乎在对 Silverlight 和 WPF 的测试中都运行良好,虽然它并没有使事情变得更快,但在我的特定场景中给人的感觉是快了 50%.

Does this seem like a sound approach? any pitfalls? It seems to work well in testing both for Silverlight and WPF, and while it doesn't make things any faster it gives the perception of being as much as 50% snappier in my specific scenario.

推荐答案

我遇到了同样的问题(在 Silverlight 项目中),并以几乎相同的方式解决了它.事实证明,它按预期工作,尚未遇到任何陷阱.

I had the same problem (in a Silverlight project), and solved it in nearly the same way. It proved to be working as expected, have not encountered any pitfalls yet.

当您需要控制解析 xaml 和实例化视图元素的时间点时,您始终可以使用 DataTemplates(不一定与 ContentControl 结合使用).您可以调用 DataTemplate.LoadContent() 来初始化它,您不必切换 ContentControl 的可见性(尽管在内部这会导致这样的 LoadContent 调用).

When you need to control the point in time when xaml is parsed and view elements are instantiated you can always use DataTemplates (not necessarily in cunjuction with ContentControl). You can call DataTemplate.LoadContent() to instatiate it, you don't have to switch the visibility of a ContentControl (although internally this will result in such a LoadContent call).

如果需要,请查看我的实现,它甚至可以在构建更重的 VisualTree 时显示静态文本消息:

Have a look at my implementation if you want, it can even display a static text message while the heavier VisualTree is build:

<DeferredContent HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <DeferredContent.DeferredContentTemplate>
        <DataTemplate>
            <MyHeavyView/>
        </DataTemplate>
    </Controls:DeferredContent.DeferredContentTemplate>
    <TextBlock Text="Loading content..."/>
</Controls:DeferredContent>

和代码

public class DeferredContent : ContentPresenter
{
    public DataTemplate DeferredContentTemplate
    {
        get { return (DataTemplate)GetValue(DeferredContentTemplateProperty); }
        set { SetValue(DeferredContentTemplateProperty, value); }
    }

    public static readonly DependencyProperty DeferredContentTemplateProperty =
        DependencyProperty.Register("DeferredContentTemplate",
        typeof(DataTemplate), typeof(DeferredContent), null);

    public DeferredContent()
    {
        Loaded += HandleLoaded;
    }

    private void HandleLoaded(object sender, RoutedEventArgs e)
    {
        Loaded -= HandleLoaded;
        Deployment.Current.Dispatcher.BeginInvoke(ShowDeferredContent);
    }

    public void ShowDeferredContent()
    {   
        if (DeferredContentTemplate != null)
        {
            Content = DeferredContentTemplate.LoadContent();
            RaiseDeferredContentLoaded();
        }
    }

    private void RaiseDeferredContentLoaded()
    {
        var handlers = DeferredContentLoaded;
        if (handlers != null)
        {
            handlers( this, new RoutedEventArgs() );
        }
    }

    public event EventHandler<RoutedEventArgs> DeferredContentLoaded;
}

这篇关于延迟加载 XAML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆