使用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; } }
这里只是一种实现思路,大家如果有更好的实现方式或意见,欢迎大家指点。