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; }

    }

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

你可能感兴趣的:(treeview)