TreeView数据的延迟加载

  使用TreeView时,很多人都应该遇到过当数据项特别多的时候,界面加载很慢的情况,用户体验很差,为了解决这个问题,这里我想到使用延时加载子项的方法去实现,即:我们显示的数据项,用户不一定所有项都很用到,初始化时,我们只加载根节点数据显示在界面,当展开根节点时,只加载根节点子项的数据,子项的子项数据不加载,依次类推,这样就解决了一次加载很多数据,界面初始化需要很长时间的问题。

  最近在看X女特工,感觉还可以,一个国家的成立需要牺牲很多人,其中也包括很多无辜的人,一份最终走到一起爱情也不是一天两天就可以,彼此都有许多苦衷,我觉得,最重要还是相互信任,不管对方做什么信任是很重要的,事实总会有一天浮出水面,结局也很好,没有吊人胃口,最终走到了一起,虽然很多枪战场面很假,毕竟消磨时间而已,无需计较,不过最后一集爆炸场面挺多的,看来要结局了,把能用的炸药都用了。

  我们同一时间终须去专心的去做某一项工作,当同时进行的任务多了,我们的效率反而会降低,我们大脑不是多核,不会并行计算,但合理的安排也会使我们提高工作效率的,休息的时候休息,玩的时候玩,工作的时候就专心工作,随心而做,就会倍感轻松。

  无聊的时候扯扯,空闲的时候扯扯,生活需扯,有扯的生活就不会太无聊,另外有期待的生活也会充满激情,比如等待一部电视剧的更新,比如期待的爱情。

  下面进入正题,如何实现数据的延时加载,这里我的思路的重新TreeViewItem项,定义一个事件,当TreeViewItem展开时触发加载事件,以下是我的代码实现,这里监听的TreeViewItem里面的ToggleButton单击事件

 public class TreeItemBase : TreeViewItem
    {
        static TreeItemBase()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeItemBase), new FrameworkPropertyMetadata(typeof(TreeItemBase)));
        }

        public TreeItemBase()
        {
            this.Expanded += new RoutedEventHandler(TreeItemBase_Expanded);
        }

        public event Func<TreeItemBase, IEnumerable<TreeItemBase>> GetChidren;

        ToggleButton _ToggleButton = null;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _ToggleButton = this.GetTemplateChild("Expander") as ToggleButton;
            _ToggleButton.Click += new RoutedEventHandler(TreeItemBase_Expanded);
        }

        void TreeItemBase_Expanded(object sender, RoutedEventArgs e)
        {
            var btn = sender as ToggleButton;

            if (this.GetChidren != null)
            {
                //TODO:每次加载计算,或第一次加载计算
                var childs = this.GetChidren(this);
                if (childs.Count() != 0)
                {
                    _ToggleButton.Visibility = System.Windows.Visibility.Visible;
                    this.BeginInit();
                    this.Items.Clear();
                    childs.ToList().ForEach(i => { this.Items.Add(i); });
                    this.EndInit();
                    if (btn != null)
                    {
                        this.IsExpanded = btn.IsChecked == true;
                    }
                }
                else//如果没有数据将Item前的button隐藏掉
                {
                    if (_ToggleButton != null)
                    {
                        _ToggleButton.Visibility = System.Windows.Visibility.Collapsed;
                    }
                }
            }
        }
另外模板也有地方需要修改,就是IsChecked绑定IsExpanded属性否则,双击TreeViewItem加载数据事件不会触发
<Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate TargetType="gl:TreeItemBase">          
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" MinWidth="19" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                        <ToggleButton IsChecked="{TemplateBinding IsExpanded}" ClickMode="Press" Name="Expander">

另外贴上我的测试代码

        IList<Item> data = new List<Item>();

        public MainWindow()
        {
            InitializeComponent();


            var group0 = new Item() { Id = Guid.NewGuid().ToString(), Header = "Root1" };
            group0.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var group1 = new Item() { Id = Guid.NewGuid().ToString(), Header = "Root0" };
            group1.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item1 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = group1.Id, Header = "Leaf1" };
            item1.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item2 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = group1.Id, Header = "Leaf2" };
            item2.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item3 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = group1.Id, Header = "Leaf3" };
            item3.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item4 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = item3.Id, Header = "Leaf3:Leaf1" };
            item4.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item5 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = item3.Id, Header = "Leaf3:Leaf2" };
            item5.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            var item6 = new Item() { Id = Guid.NewGuid().ToString(), ParentId = item3.Id, Header = "Leaf3:Leaf3" };
            item6.GetChidren += new Func<TreeItemBase, IEnumerable<TreeItemBase>>(group1_GetChidren);

            data.Add(group1);
            data.Add(item1);
            data.Add(item2);
            data.Add(item3);
            data.Add(item4);
            data.Add(item5);
            data.Add(item6);


            group0.Items.Add(group1);
            treeView1.ItemsSource = group0.Items;


        }

        IEnumerable<TreeItemBase> group1_GetChidren(TreeItemBase arg)
        {
            return data.Where(e => e.ParentId == (arg as Item).Id);
        }


    public class Item : TreeItemBase
    {
        public string Id { get; set; }

        public string ParentId { get; set; }
    }

这里只是一种实现思路,大家如果有更好的实现方式或意见,欢迎大家指点。

原文地址:https://www.cnblogs.com/guanglin/p/3028511.html