从HierarchicalDataTemplate派生

时间:2018-09-09 18:37:07

标签: c# wpf hierarchicaldatatemplate

我想在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的内部细节是什么。

0 个答案:

没有答案