WPF如何用TreeView制作好友列表、播放列表

闪电
闪电
闪电
57
文章
0
评论
2020年4月27日15:06:12 评论 159

前言

  TreeView这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表)、音乐播放器(播放列表)、类库展示器(树形类结构)等都用的是TreeView,下面以一个好友列表为例,说明一下制作过程,这个过程可以搬迁到其他类似的场景中去(树形结构的场景)。

结果展示

  

WPF如何用TreeView制作好友列表、播放列表

制作过程

  1. 新建一个WPF工程,我命名为TreeViewDemo。(这步不解释)

  2. 准备图片,就是系统头像。在工程中新建一个Heads文件夹,并且添加系统头像图片,最后不要忘记需要把生成方式改为Resource、不复制,这样才能用标准的Pack URI的方式来读取到图片。(我喜欢用Pack Uri,因为比较通用,安全) 下载头像

  3. 好了,资源图片准备好了以后,来定义数据类,在这里我们需要用到两个类,一个代表好友,一个代表好友列表(对应的音乐播放器就是音乐和音乐列表)。

#Friend(好友)

class Friend
    {
        public Friend(FriendList list)
        {
            this.List = list;
        }
        //头像的路径
        public String HeadPath { set; get; }
        //好友名字
        public String Name { set; get; }
        //签名
        public String Autograph { set; get; }

        public FriendList List { set; get; }

    }
#FriendList(好友列表)

class FriendList
    {
        public FriendList(String name)
        {
            this.ListName = name;
        }
        public String ListName { set; get; }

        private ObservableCollection<Friend> _friends = new ObservableCollection<Friend>();
        public ObservableCollection<Friend> Friends
        {
            private set{}
            get
            {
                return _friends;
            }
        }

        public void AddFriend(Friend newFriend)
        {
            _friends.Add(newFriend);
        }

        public void RemoveFriend(Friend friend)
        {
            _friends.Remove(friend);
        }
    }

  4. 这一步是重点,就是在一个TreeView的节点中,如何去区分Friend和FriendList呢?我使用模板,我分别为Friend和FriendList定义属于它们各自的模板,一起定义在一个字典中,新建一个字典,我命名为GlobeDictionary。这里应该要用的是数据模板(DataTemplate),系统有一个数据模板叫HierarchicalDataTemplate,这个模板专门用于有头部和子数据的数据结构的,用在这个TreeView中刚好合适。



    
        
            
        
    
    
        
            
                
                
            
            
            
                
                    
                    
                
            
        
    

  (注意:因为需要再这里引用自定义类,所以命名空间local的引入一定要正确,冲上面的定义可以看出,好友列表只显示名字,好友就用Grid来组织一个类QQ的布局,头像,签名等。)

  5. 主界面。

  主界面比较简单,在这个Demo中,只使用TreeView控件。


    
        
    

  

  6. 有了躯壳,我们填入灵魂(数据绑定和数据模板应用)。

  模板有两个,直接填充TreeView的ItemTemplate属性是不行的,但是WPF中有一个思想很重要(Selector、Converter等),在TreeView中有一个属性ItemTemplateSelector。所以,新建一个Selector类,继承DataTemplateSelector:

class FriendOrListTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            ResourceDictionary directory = new ResourceDictionary();
            directory.Source = new Uri("pack://Application:,,,/GlobeDictionary.xaml", UriKind.RelativeOrAbsolute);//使用pack uri载入模板字典
            if (item != null && item is FriendList)
            {
                return directory["ListTemple"] as DataTemplate;
            }
            return directory["FriendTemple"] as DataTemplate;
        }
    }

  首先使用pack uri加载位于当前exe程序集中的字典资源(如果加载不了,请将字典生成方式改为Resource),然后根据传入的数据类型来返回对应的DataTemplate,这样就能有效的自动选择模板。

  模板能自动选择了,另外数据怎么提供呢,我们使用在WPF中最常用的DataContext绑定来填充ItemsSource。下面看主界面的完整代码。


    
        
            
        
        
        
    

  这里的命名空间local是FriendOrListTemplateSelector所在的命名空间中,请填写对。最后在主界面的代码中加入数据,测试一下。

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ObservableCollection Root = new ObservableCollection();
            FriendList listOne = new FriendList("高中同学");
            Friend friend1 = new Friend(listOne) { Autograph = "今天很开心,遇到了XX", HeadPath = "Heads/h1.png", Name = "天煞" };
            Friend friend2 = new Friend(listOne) { Autograph = "非一般的感觉", HeadPath = "Heads/h2.png", Name = "Basx" };
            Friend friend3 = new Friend(listOne) { Autograph = "WER", HeadPath = "Heads/h3.png", Name = "Paul" };
            Friend friend4 = new Friend(listOne) { Autograph = "~终于完成作业了~~!", HeadPath = "Heads/h4.png", Name = "孤星月" };
            listOne.AddFriend(friend1);
            listOne.AddFriend(friend2);
            listOne.AddFriend(friend3);
            listOne.AddFriend(friend4);
            FriendList listTwo = new FriendList("大一");
            Friend friend5 = new Friend(listOne) { Autograph = "你的存在", HeadPath = "Heads/h5.png", Name = "菲菲" };
            listTwo.AddFriend(friend5);
            Root.Add(listOne);
            Root.Add(listTwo);
            this.ListTV.DataContext = Root;
        }
    }

  大功告成~!

总结

  过程比较简单,但是最重要的是学习其方法,有几点通用的知识需要注意的:

    1. Xaml中需要使用自定义类的时候,需要在头部xmlns中添加一项,并且确保命名空间是对的。

    2. Pack URI的使用,任何资源的引用都可以使用Pack URI,下面举两个例子:

      *pack://Application:,,,/路径/路径/文件名(带后缀) <-这种方式是引用当前程序集的Resouce资源的。

      *pack://Application:,,,/引用的程序集名称;component/路径/路径/文件名(带后缀)<-这种方式是引用其他程序集的Resouce资源的。

    3. 选择器(Selecter),转换器(Converter)等的思想要深入理解。

    4. 数据模板是为数据定制外观,例如这里就为Friend和FriendList定制了外观了。

完整Demo下载

继续阅读
weinxin
我的微信
微信扫一扫
闪电
  • 本文由 发表于 2020年4月27日15:06:12
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
WPF多线程UI更新——两种方法 .NET

WPF多线程UI更新——两种方法

前言     在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对象。)这是很常见的一个错误...
WPF 蒙罩层 LoadingPage .NET

WPF 蒙罩层 LoadingPage

前言   无论是在PC客户端,移动端,网站,在遇到长时间处理的时候都会需要用到蒙罩层,让用户有更好的体现。今天上网逛了一下各位前辈网友的蒙罩层的实现方式,觉得有很多都搞复杂了(利用前台代码+后台代码+...
.NET 压缩解压库发布,支持进度查看 .NET

.NET 压缩解压库发布,支持进度查看

发布了一个 .net压缩解压库,基于SharpZipLib开发 ,支持进度查看,支持路径保持与否。 () 是一个基于SharpZipLib的一个压缩和解压的类库,提供给用户在.net环境下使用(VB....
.NET在EF中使用sql,用动态类吧! .NET

.NET在EF中使用sql,用动态类吧!

前言   在.NET中使用Entity Framework能快速、方便地结合LINQ来对数据库进行一系列的增删改查操作。但是由于EF根据表达式最后生成通用的sql来执行,进行具体的数据库操作。根据本人...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: