Problem

TreeListView Items don't show when IsDataVirtualizationEnabled = true

Posted 1 year ago by Avatar Peter McKinnis

When the `IsDataVirtualizationEnabled` is set to `true` on a TreeListView.   The content for many (about half) items are missing when scrolling.  Whether or not an item has missing content depends on the scroll speed, direction, and history.    The immediate window gives a binding error for each item with missing content (see below).  It seems like the TreeGridView is attempting to bind to items before they are loaded.  The documentation indicates that this could be related to the VirtualizationMode.  However, changing VirtualizingPanel.VirtualizationMode="Standard" does not fix the issue.  However, it does seem to change which items have missing content.   

Binding Error:

System.Windows.Data Error: 40 : BindingExpression path error: 'Ln' property not found on 'object' ''#kzj' (HashCode=63658128)'.
BindingExpression:Path=Ln; DataItem='#kzj' (HashCode=63658128); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

 Code to replicate the issue:

<Window x:Class="TreeGridView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:grids="http://schemas.actiprosoftware.com/winfx/xaml/grids"
        xmlns:local="clr-namespace:TreeGridView"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    
    <grids:TreeListView 
        RootItem="{Binding}" 
        IsDataVirtualizationEnabled="True">
        <grids:TreeListBox.ItemAdapter>
            <grids:TreeListBoxItemAdapter ChildrenBinding="{Binding Children}" ChildrenPath="Children" />
        </grids:TreeListBox.ItemAdapter>

        <grids:TreeListView.Columns>
            <grids:TreeListViewColumn Header="Child Count">
                <DataTemplate>
                    <TextBlock Text="{Binding ChildCount}" VerticalAlignment="Center" />
                </DataTemplate>
            </grids:TreeListViewColumn>
            <grids:TreeListViewColumn Header="Sqrt">
                <DataTemplate>
                    <TextBlock Text="{Binding Sqrt}" VerticalAlignment="Center" />
                </DataTemplate>
            </grids:TreeListViewColumn>
            <grids:TreeListViewColumn Header="Ln">
                <DataTemplate>
                    <TextBlock Text="{Binding Ln}" VerticalAlignment="Center" />
                </DataTemplate>
            </grids:TreeListViewColumn>
        </grids:TreeListView.Columns>
    </grids:TreeListView>
</Window>

 

 

using System;
using System.Windows;
using System.Collections;

namespace TreeGridView
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new TreeNode(500000);
        }
    }
    
    public class TreeNode
    {

        public TreeNode(int childCount)
        {
            Children = new VirturalList(childCount);
            ChildCount = childCount;
            Sqrt = Math.Sqrt(childCount);
            Ln = Math.Log(childCount);
        }

        public double ChildCount { get; }
        public double Sqrt { get; }
        public double Ln { get; }
        public IList Children { get; }

    }

    public class VirturalList : IList
    {

        public VirturalList(int count)
        {
            Count = count;
        }

        public int Count { get; }

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < Count; i += 1)
            {
                yield return this[i];
            }
        }

        public object this[int index]
        {
            get
            {
                return new TreeNode(index);
            }
            set => throw new NotImplementedException();
        }
        
        public bool IsReadOnly => throw new NotImplementedException();
        public bool IsFixedSize => throw new NotImplementedException();
        public object SyncRoot => throw new NotImplementedException();
        public bool IsSynchronized => throw new NotImplementedException();
        public int Add(object value) => throw new NotImplementedException();
        public void Clear() => throw new NotImplementedException();
        public bool Contains(object value) => throw new NotImplementedException();
        public void CopyTo(Array array, int index) => throw new NotImplementedException();
        public int IndexOf(object value) => throw new NotImplementedException();
        public void Insert(int index, object value) => throw new NotImplementedException();
        public void Remove(object value) => throw new NotImplementedException();
        public void RemoveAt(int index) => throw new NotImplementedException();
    }
}

Comments (1)

Posted 1 year ago by Actipro Software Support - Cleveland, OH, USA

Hi Peter,

Thanks for letting us know.  It seems that in TreeListView scenarios where data virtualization is enabled, we need to manually update the generated TreeListViewItem container's DataContext to get it to flow down correctly.  We've done so for the upcoming build.  Please write our support address if you'd like to test a preview build.

Also as a side note, you have millions of data items in this example.  The tree will operate much faster if you set ChildrenQueryModeDefault="OnExpansion" on your adapter.


Actipro Software Support
Information The latest build of this product (2018.1 build 0674) was released 4 days ago, which was after the last post in this thread.

Add a Comment

Please log in to a validated account to post comments.