WPF - Treeview和ContentControl虚拟化

问题描述 投票:0回答:2

我有一个treeview,其中包含自定义类TreeviewItem项的itemsource。

我有一个TreeviewItem类型的属性SelectedTreeviewItemViewModel。

public TreeviewItem SelectedTreeviewItemViewModel //with INPC

我在窗口的其他地方有一个内容控件

        <ContentControl Content="{Binding SelectedTreeviewItemViewModel}" /> 

使用datatemplate如下:

    <DataTemplate DataType="{x:Type TreeviewItem}">
        <uc:TreeviewCustomView />
    </DataTemplate>

当我单击treeview的一个项目时,会触发事件SelectedItemChanged,并设置SelectedTreeviewItemViewModel,它强制contentcontrol刷新其内容。

逻辑很好,但是我注意到当我点击树视图中的新项目时,一些数据会更新但我不会进入用户控件的构造函数(uc:TreeviewCustomView)。

是否涉及某种虚拟化?我猜WPF缓存datatemplate;有没有什么办法可以强制WPF每次点击树视图项时从头开始重新创建用户控件(从而进入构造函数)?

c# wpf treeview contentcontrol
2个回答
1
投票

使用绑定时,默认情况下会对TreeView进行虚拟化。如果将模式切换到VirtualizingPanel.VirtualizationMode =“Standard”而不是“Recycling”,则应调用构造函数。


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 }" />
© www.soinside.com 2019 - 2024. All rights reserved.