我正在处理的一个项目有一些相当复杂的 XAML,它明显影响了视觉性能。相当多的控件在初始状态下是折叠的;然而,由于它们的 XAML 已被解析并构建了可视化/逻辑树,因此显示几乎空白对象的速度非常慢。
看起来(并且需要在此确认)使用初始状态为 Collapsed 的 ContentControl,然后将所需的控件作为该 ContentControl 的 DataTemplate 嵌入,将推迟在 DataTemplate 中加载所需的控件,直到 ContentControl 可见。
我构建了一个通用的 DeferredContentControl 来监听主 UI 控件的 LayoutUpdated 事件(一般来说,无论我想要快速显示的元素是什么),当该 UIElement 的第一个 LayoutUpdated 事件触发时,我使用 Dispatcher 来翻转DeferredContentControl 的可见性设置为 true,这会导致 DeferredContentControl 的 DataTemplate 中的控件进行实例化。当用户对屏幕的初始视图(现在速度很快)做出反应时,数据模板中的“加载缓慢”(但仍然折叠)控件已准备就绪。
这看起来是一个合理的方法吗?有什么陷阱吗?它似乎在 Silverlight 和 WPF 的测试中都表现良好,虽然它没有使事情变得更快,但在我的特定场景中,它给人的感觉是快了 50%。
我遇到了同样的问题(在 Silverlight 项目中),并以几乎相同的方式解决了它。事实证明,它按预期工作,尚未遇到任何陷阱。
当您需要控制解析 xaml 和实例化视图元素的时间点时,您始终可以使用DataTemplates
(不一定要与ContentControl
)。您可以致电DataTemplate.LoadContent()
要实例化它,您不必切换 ContentControl 的可见性(尽管在内部这将导致这样的 Load Content 调用)。
如果您愿意,请查看我的实现,它甚至可以在构建较重的 VisualTree 时显示静态文本消息:
<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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)