我想在WPF中对TreeViewItem执行延迟加载。我已经知道将一些“虚拟”项目添加到ItemsSource并在Expanded事件上将该虚拟项目与真实列表交换的常见答案。
原始TreeViewItem的问题在于,它总是访问至少在第一层不希望的原始列表,但是由于建立第二层会导致大量流量,因此我无法允许这种行为
修改HasItems属性实际上并不起作用,因为HasItems属性在TreeViewItem中进行了深度编码。因此,我决定将一个LazyItemsSource添加到TreeViewItem(DynamicTreeViewItem),如果有人展开该节点,则LazyItemsSource将分配给ItemsSource。
问题是我需要通过HierarchicalDataTemplate控制层次结构。我没有分配模板中的ItemsSource,而是分配了LazyItemsSource,但是以某种方式是不可能的。显示的错误是:
错误MC4104:无法将属性“ LazyItemsSource”设置为模板上的属性元素。只允许将触发器和情节提要用作属性元素。第10行的位置79。
但是我不知道为什么编译器会对此抱怨。 这是源代码:
using System.Collections;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp8
{
public class DynamicTreeView : TreeView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new DynamicTreeViewItem();
}
}
public class DynamicTreeViewItem : TreeViewItem
{
public static readonly DependencyProperty LazyItemsSourceProperty
= DependencyProperty.Register("LazyItemsSource", typeof(IEnumerable), typeof(ItemsControl),
new FrameworkPropertyMetadata((IEnumerable)null,
new PropertyChangedCallback(OnLazyItemsSourceChanged)));
public bool IsSourceAssigned
{
get;
private set;
} = false;
public IEnumerable LazyItemsSource
{
get => (IEnumerable)GetValue(LazyItemsSourceProperty);
set => SetValue(LazyItemsSourceProperty, value);
}
private static void OnLazyItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if (e.Property == IsExpandedProperty)
{
if (!IsSourceAssigned)
{
SetValue(ItemsSourceProperty, new int[] { 1, 2, 3, 4, 5 });
IsSourceAssigned = true;
}
}
base.OnPropertyChanged(e);
}
private readonly static IEnumerable LazySource = new ArrayList(new[] { new object() });
public DynamicTreeViewItem()
{
Loaded += DynamicTreeViewItem_Loaded;
}
private void DynamicTreeViewItem_Loaded(object sender, RoutedEventArgs e)
{
SetValue(ItemsSourceProperty, LazySource);
}
}
public class DynamicHierarchicalDataTemplate : HierarchicalDataTemplate
{
public IEnumerable LazyItemsSource
{
get;
set;
}
}
}
以及XAML:
<Window x:Class="WpfApp8.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:local="clr-namespace:WpfApp8"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:DynamicHierarchicalDataTemplate DataType="{x:Type local:Node}" LazyItemsSource="{Binding Items}">
<TextBlock Text="{Binding}"/>
</local:DynamicHierarchicalDataTemplate>
</Window.Resources>
<Grid>
<local:DynamicTreeView ItemsSource="{Binding Tree.Items}"/>
</Grid>
</Window>
我目前可以使用此解决方案,但是我不知道是什么导致编译器抱怨:
<HierarchicalDataTemplate DataType="{x:Type local:Node}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type local:DynamicTreeViewItem}">
<Setter Property="LazyItemsSource" Value="{Binding Items}"/>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
我觉得这应该是一件很容易的事,但是我不确定DataTemplate的内部细节是什么。