TreeViewItem Виртуализация и пользовательские свойства DependencyProperty (C# и WPF) - PullRequest
2 голосов
/ 01 апреля 2020

Intro

У меня проблема с элементом управления WPF TreeView Виртуализация. Я думаю, что я достиг возможностей с этим контролем и вроде как выяснил почему. Может быть, кто-то может помочь найти лучшее решение для этого.

Проблема

У меня есть собственный элемент управления TreeListView, унаследованный от TreeView и TreeListViewItem, унаследованный от TreeViewItem. Для TreeListView я использую виртуализацию. Я добавил DependencyProperty к TreeListViewItem.

public static readonly DependencyProperty IsItemSelectedProperty = DependencyProperty.Register(
  "IsItemSelected", typeof(bool), typeof(TreeListViewItem), new FrameworkPropertyMetadata(
    false, new PropertyChangedCallback(OnIsItemSelectedChanged)
    )
  ;

public bool IsItemSelected
{
  get { return (bool)GetValue(IsItemSelectedProperty); }
  set { SetValue(IsItemSelectedProperty, value); }
}

При активной виртуализации DP либо (VirtualizationMode = Recycling) неправильно используется для новых элементов при прокрутке, либо (VirtualizationMode = Normal) больше не существует.

Причина

TreeView не сохраняет свойства в режиме виртуализации. Я копался в коде TreeViewItem и нашел код, который "вызывает" это.

TreeViewItem.cs line 910 Функция ClearItemContainer:
https://referencesource.microsoft.com/#PresentationFramework / src / Framework / System / Windows / Controls /TreeViewItem.cs

// Right now we have a hard-coded list of DPs we want to save off.  In the future we could provide a 'register' API
// so that each ItemsControl could decide what DPs to save on its containers. Maybe we define a virtual method to
// retrieve a list of DPs the type is interested in.  Alternatively we could have the contract
// be that ItemsControls use the ItemStorageService inside their ClearContainerForItemOverride by calling into StoreItemValues.

В строке Helper.cs 1554:
https://referencesource.microsoft.com/#PresentationFramework / src / Framework / MS / Internal / Helper.cs, de11b95141f7f543

// Since ItemValueStorage is private and only used for TreeView and Grouping virtualization we hardcode the DPs that we'll store in it.
// If we make this available as a service to the rest of the platform we'd come up with some sort of DP registration mechanism.
private static readonly int[] ItemValueStorageIndices = new int[] {
    ItemValueStorageField.GlobalIndex,
    TreeViewItem.IsExpandedProperty.GlobalIndex,
    Expander.IsExpandedProperty.GlobalIndex,
    GroupItem.DesiredPixelItemsSizeCorrectionFactorField.GlobalIndex,
    VirtualizingStackPanel.ItemsHostInsetProperty.GlobalIndex};

Таким образом, единственным сохраненным свойством является IsExpandedProperty. И невозможно добавить собственные свойства.

Что делать?

Есть ли какой-то другой способ, которым я не вижу добавления свойств?
Есть ли способ сохранить свойства самостоятельно?

...