文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>MVVM打造无限级TreeView

MVVM打造无限级TreeView

时间:2010-09-02  来源:囧月

    自从了解了MVVM,就迷恋上了它,基本上抛弃了传统的开发方式~

    前些天无意中看到一篇关于用MVVM打造TreeView的文章(http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx),感觉比较美妙,遂拿来简单改造一下,使它支持无限级。

    首先,定义一个实体类:

    public class TreeItem
    {
        readonly List<TreeItem> _children = new List<TreeItem>();
        public List<TreeItem> Children
        {
            get { return _children; }
        }

        public string Name { get; set; }
        public int ID { get; set; }
        public int ParentID { get; set; }
    }

 

    接下来,把TreeViewItemViewModel、以及PropertyChangedBase直接搬过来。

    然后定义一个ViewModel:

   public class TreeItemViewModel : TreeViewItemViewModel
        {
                private TreeItem item;

                public TreeItemViewModel(TreeItem item) :
                        this(item, null)
                {

                }

                public TreeItemViewModel(TreeItem item, TreeItemViewModel parent) :
                        base(parent, true)
                {
                        this.item = item;
                }

                public string Name
                {
                        get { return item.Name; }
                        set
                        {
                                item.Name = value;
                                this.NotifyPropertyChanged(p => p.Name);
                        }
                }
                
                protected override void LoadChildren()
                {
                        var loadedData = TreeItemDemoData.LoadChildrens(item.ID);
                        if (loadedData.Count > 0)
                        {
                                Children.Clear();
                                foreach (var t in loadedData)
                                {
                                        Children.Add(new TreeItemViewModel(t, this));
                                }
                        }
                }
        }

 

    以及相关Demo数据:

   public class TreeItemDemoData
        {
                private static readonly List<TreeItem> data;

                static TreeItemDemoData()
                {
                        data = new List<TreeItem>();
                        for (int i = 0; i < 10; i++)
                        {
                                data.Add(new TreeItem
                         {
                                Name = string.Format("Name {0}", i.ToString()),
                                ID = i,
                                ParentID = i - 1
                         });
                        }
                }

                public static List<TreeItem> LoadChildrens(int parentId)
                {
                        return data.Where(t => t.ParentID == parentId).ToList();
                }
        }

 

    定义界面:

<Window x:Class="TreeViewDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:TreeViewDemo.ViewModel"
        Title="TreeViewDemo" Height="300" Width="300"
>
        <StackPanel>
                <TreeView ItemsSource="{Binding}">
                        <TreeView.ItemContainerStyle>
                                <Style TargetType="{x:Type TreeViewItem}">
                                        <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                                        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                                        <Setter Property="FontWeight" Value="Normal" />
                                        <Style.Triggers>
                                                <Trigger Property="IsSelected" Value="True">
                                                        <Setter Property="FontWeight" Value="Bold" />
                                                </Trigger>
                                        </Style.Triggers>
                                </Style>
                        </TreeView.ItemContainerStyle>
                        <TreeView.Resources>
                                <HierarchicalDataTemplate
                                        DataType="{x:Type vm:TreeItemViewModel}"
                                        ItemsSource="{Binding Children}">
                                        <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="{Binding Name}" />
                                        </StackPanel>
                                </HierarchicalDataTemplate>
                        </TreeView.Resources>
                </TreeView>
        </StackPanel>
</Window>

 

    最后,绑定数据:

   public partial class Window1 : Window
        {
                public Window1()
                {
                        InitializeComponent();
                        DataContext = new ObservableCollection<TreeItemViewModel>(
                                TreeItemDemoData.LoadChildrens(0).Select(t => new TreeItemViewModel(t))
                        );
                }
        }

    OK,完成,发现HierarchicalDataTemplate挺神奇的~_~。

 

    相信TreeView应用范围还是相当广的,比如某些应用的数据N级分类。

    当然,如果是数据库应用,可能会有一定延迟,造成界面的假死,在此对本文例子稍加改造,使用多线程提高UI的响应速度。

    对TreeItemViewModel进行改造:

           protected override void LoadChildren()
                {
                        PreLoad();
                }
                
                private string originalName;
                private Dispatcher uiThreadDispatcher;
                private void PreLoad()
                {
                        originalName = Name;
                        Name = Name + " (expanding...)";
                        uiThreadDispatcher = Dispatcher.CurrentDispatcher;                      
                        ThreadPool.QueueUserWorkItem(Loading);
                }
                
                private void Loading(object state)
                {
                        Thread.Sleep(500);//模拟延迟
                        var loadedData = TreeItemDemoData.LoadChildrens(item.ID);
                        if (loadedData.Count > 0)
                        {
                                uiThreadDispatcher.BeginInvoke(DispatcherPriority.Background,
                                                               new Action(() => Children.Clear()));
                                foreach (var t in loadedData)
                                {
                                        uiThreadDispatcher.BeginInvoke(DispatcherPriority.Background,
                                                                       new Action<TreeItem>(vm => Children.Add(new TreeItemViewModel(vm, this))),
                                                                       t);
                                }
                        }
                        Name = originalName;
                }

    只是简单的小技巧~本文就到这里。

    DEMO地址

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载