我有一个带有itemsource的树状视图,其中包含自定义类TreeviewItem的项目。
我具有TreeviewItem类型的属性SelectedTreeviewItemViewModel。
public TreeviewItem SelectedTreeviewItemViewModel //with INPC
我在窗口的其他地方有一个内容控件
<ContentControl Content="{Binding SelectedTreeviewItemViewModel}" />
具有如下数据模板:
<DataTemplate DataType="{x:Type TreeviewItem}">
<uc:TreeviewCustomView />
</DataTemplate>
当我单击树视图的一个项目时,将触发事件SelectedItemChanged,并设置SelectedTreeviewItemViewModel,这将迫使contentcontrol刷新其内容。
逻辑很好,但是我注意到当我在树视图中单击一个新项时,一些数据已更新,但是我没有进入用户控件的构造函数(uc:TreeviewCustomView)。
是否涉及某种虚拟化?我猜WPF缓存数据模板;有什么方法可以强制WPF每次我单击树视图项目时从头重新创建用户控件(从而进入构造函数)?
答案 0 :(得分:1)
在使用绑定时,TreeView默认情况下是虚拟化的。 如果将模式切换为VirtualizingPanel.VirtualizationMode =“ Standard”而不是“ Recycling”,则应调用构造函数。
答案 1 :(得分:1)
这是给我带来麻烦的方法:
我创建了一个模板选择器,该选择器基本上将模板包装在另一个模板中,强制创建新实例。 请记住,这可能会导致严重的性能问题!
在我的xaml中,我首先命名数据模板:
<DataTemplate x:Key="TreeviewItemTemplate" DataType="{x:Type TreeviewItem}">
<uc:TreeviewCustomView />
</DataTemplate>
然后我创建一个模板选择器,如下所示:
public class TreeviewItemTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null)
{
return null;
}
var declaredDataTemplate = ((FrameworkElement)container).FindResource("TreeviewItemTemplate") as DataTemplate;
var wrappedDataTemplate = WrapDataTemplate(declaredDataTemplate );
return wrappedDataTemplate;
}
private static DataTemplate WrapDataTemplate(DataTemplate declaredDataTemplate)
{
var frameworkElementFactory = new FrameworkElementFactory(typeof(ContentPresenter));
frameworkElementFactory.SetValue(ContentPresenter.ContentTemplateProperty, declaredDataTemplate);
var dataTemplate = new DataTemplate();
dataTemplate.VisualTree = frameworkElementFactory;
return dataTemplate;
}
}
最后,我在内容控件上使用选择器:
<ContentControl Content="{Binding SelectedTreeviewItemViewModel }"
ContentTemplateSelector="{StaticResource TreeviewItemTemplateSelector }" />