我正在研究的项目有一些相当复杂的XAML,它会显着影响视觉效果。对于初始状态,相当多的控件都被折叠了;但是,由于他们的XAML被解析并且构建了视觉/逻辑树,因此显示几乎是空白对象的速度非常慢。
看起来(并且希望在此确认)使用初始状态为Collapsed的ContentControl,然后将所需控件作为DataConmplate嵌入到该ContentControl中,将推迟在DataTemplate中加载所需控件,直到ContentControl为显而易见。
我已经构建了一个通用的DeferredContentControl,用于侦听主UI控件的LayoutUpdated事件(通常是我希望快速显示的任何元素),当该UIElement的第一个LayoutUpdated事件触发时,我使用Dispatcher将DeferredContentControl的可见性翻转为true,这会导致DeferredContentControl的DataTemplate中的控件实例化。当用户对屏幕的初始视图(现在快速)做出反应时,"加载缓慢" (但仍然已折叠)数据模板中的控件已准备就绪。
这看起来像是一种合理的方法吗?任何陷阱?它似乎可以很好地测试Silverlight和WPF,虽然它不会让事情变得更快,但它让我觉得在我的特定场景中有50%的速度更快。
答案 0 :(得分:6)
我遇到了同样的问题(在Silverlight项目中),并以几乎相同的方式解决了它。事实证明它已按预期工作,尚未遇到任何陷阱。
当你需要控制解析xaml和实例化视图元素的时间点时,你总是可以使用DataTemplates
(不一定与ContentControl
一起使用)。您可以调用DataTemplate.LoadContent()
来实例化它,您不必切换ContentControl的可见性(虽然在内部这将导致这样的LoadContent调用)。
如果需要,请查看我的实现,它甚至可以在构建较重的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;
}