Search code examples
c#wpfpopupui-virtualization

UI Virtualization inside Popup


I am unable to get Virtualization to work on a TreeView inside a Popup while the same TreeView works perfectly outside of Popup.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ToggleButton IsChecked="{Binding ElementName=Popup, Path=IsOpen, Mode=TwoWay}"
                      Content="Test"/>

        <TreeView Grid.Row="1" ItemsSource="{Binding Nodes}" VirtualizingPanel.IsVirtualizing="True">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Data}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

        <Popup x:Name="Popup" StaysOpen="True">
            <TreeView ItemsSource="{Binding Nodes}" VirtualizingPanel.IsVirtualizing="True">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <TextBlock Text="{Binding Data}"/>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
        </Popup>
    </Grid>

ViewModel and Node class

public class ViewModel
{
    public ObservableCollection<Node> Nodes { get; private set; }
    public ViewModel()
    {
        Nodes = new ObservableCollection<Node>();
        Node parent = new Node("Parent");

        for (int i = 0; i < 10000; i++)
            parent.Children.Add(new Node(i.ToString()));

        Nodes.Add(parent);
    }
}
public class Node
{
    public string Data { get; set; }

    public List<Node> Children { get; set; }
    public Node(string data)
    {
        Data = data;
        Children = new List<Node>();
    }
}

When I expand the parent for the tree inside the Window it takes no time while expanding the one inside popup takes ~20s.

MS confirmed this is a bug back in 2010s and suggested to use a ControlTemplate to merge the ToggleButton and TreeView into one control, but it did not have any effect for me.


Solution

  • Figured it out, all you need to do is to specify a max height (normal height works too) to the Popup

    <Popup x:Name="Popup" StaysOpen="True" MaxHeight="500">
    

    Not really sure why this helps. Maybe WPF needs to do too much size calculation if its automatic.