WPF-Treeview和ContentControl虚拟化

时间:2019-03-21 08:44:30

标签: c# wpf treeview contentcontrol

我有一个带有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每次我单击树视图项目时从头重新创建用户控件(从而进入构造函数)?

2 个答案:

答案 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 }" />
相关问题