0
votes

I have a treeview with itemsource containing items of custom class TreeviewItem.

I have a property SelectedTreeviewItemViewModel of type TreeviewItem.

public TreeviewItem SelectedTreeviewItemViewModel //with INPC

I have a content control somewhere else on the window

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

with a datatemplate as follow:

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

When I click on an item of the treeview, the event SelectedItemChanged is fired and I set SelectedTreeviewItemViewModel which forces the contentcontrol to refresh its content.

The logic is fine, however I noticed that when I click on a new item in the treeview, some data is updated but I don't step into the user control's constructor (uc:TreeviewCustomView).

Is there some kind of virtualization involved? I'm guessing WPF caches the datatemplate; is there any way I can force WPF to recreate the user control from scratch (thus stepping into the constructor) everytime I click on a treeview item?

2

2 Answers

1
votes

TreeViews are virtualized by default when using binding. If you switch the mode to VirtualizingPanel.VirtualizationMode="Standard" instead of "Recycling" the constructor should get called.

1
votes

Here's what did the trick for me:

I create a template selector which basically wraps the template in another template, forcing the creation of a new instance. Please keep in mind that this can result in severe perf problems!

In my xaml, I start by naming the data template:

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

Then I create a template selector as follow:

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;
    }
}

And finally, I use the selector on my content control:

<ContentControl Content="{Binding SelectedTreeviewItemViewModel }"
                ContentTemplateSelector="{StaticResource TreeviewItemTemplateSelector }" />