我有一个选项卡控件,其中在运行时创建选项卡。选项卡的内容将是几个用户控件之一,每个用户控件都包含数百个其他控件。由于创建这些用户控件需要很长时间,因此我试图找到一种重用它们的方法,而不是为每个选项卡创建一个新实例。
我正在使用DataTemplate设置标签页内容,如下所示:
<DataTemplate>
<ScrollViewer Content="{Binding Content}" />
</DataTemplate>
“内容”是我要在标签中显示的视图的视图模型。
在其他地方,我使用数据模板将每个视图模型映射到一个视图,例如
<DataTemplate DataType="{x:Type vm:MyViewModel1}">
<ctl:CacheContentControl ContentType="{x:Type ctl:MyView1}" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MyViewModel2}">
<ctl:CacheContentControl ContentType="{x:Type ctl:MyView2}" />
</DataTemplate>
CacheContentControl是用于缓存的ContentControl的包装:
public class CacheContentControl : ContentControl
{
private static Dictionary<Type, Control> cache = new Dictionary<Type, Control>();
public CacheContentControl()
{
Unloaded += CacheContentControl_Unloaded;
}
private void CacheContentControl_Unloaded(object sender, RoutedEventArgs e)
{
Content = null;
}
private Type _contentType;
public Type ContentType
{
get { return _contentType; }
set
{
_contentType = value;
Content = GetView(_contentType);
}
}
public Control GetView(Type type)
{
if (!cache.ContainsKey(type))
{
cache.Add(type, (Control)Activator.CreateInstance(type));
}
return cache[type];
}
}
这可确保DataTemplate在创建新实例之前先检查缓存以查看其是否可以重用控件。
这适用于创建的任何新选项卡。第一个选项卡的速度很慢,因为它需要创建初始控件,但是使用相同控件的所有后续选项卡几乎都会立即加载。我遇到的问题是,当我单击返回上一个选项卡时,该控件不再出现,并且该选项卡为空白。
我想这是因为我无法多次以相同的形式显示相同的控件实例,这是有道理的。通过将CacheContentControl的IsVisibleChanged事件处理如下,可以解决此问题:
private void CacheContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (IsVisible && ContentType != null)
{
Control ctl = GetView(_contentType);
ctl.DataContext = DataContext;
Content = ctl;
}
else
{
Content = null;
}
}
当选项卡失去焦点时,它将删除控件,接收焦点的选项卡随后可以从似乎有效的缓存中检索控件。
问题在于速度再次回到缓慢状态,我不确定为什么。显然,可以将控件实例从一个选项卡移动到另一个选项卡而无需延迟,因为每次创建新选项卡时都会这样做。为了更改控件的父级,DataTemplate必须做一些不同的事情吗?
答案 0 :(得分:0)
我不确定您是否需要去缓存用户控件,因为WPF在很大程度上为您做到了。
按类型键入键的DataTemplate内部的通常方法是不使用ContentControl,而只是使用UserControl作为模板。
data
TabControl将具有一个ContentControl,其Content设置为适用的ViewModel,WPF将使用该类型的指定DataTemplate自动呈现它并设置DataContext。
我已经按照上面概述的简单方法构建了使用DataTemplates渲染的大规模WPF视图,而没有遇到任何严重的性能问题,我认为您可以通过将ContentControl.Content绑定到ViewModel实例并让WPF处理来安全地开始开发使用上面较简单的DataTemplate方法进行渲染。