WPF做的小型音乐播放器升级版

WPF做的小型音乐播放器-升级版

对WPF越来越爱.今天早上看到一个开源的音乐播放器 豆瓣电台 ,下载了源码尝试了一下,功能很强大,样式很漂亮(推荐对WPF有兴趣的童鞋也下载来试下,学习的好机会哦).可惜,他是基于事件驱动的,主窗口cs代码有2000多行,逻辑神马的虽然放在逻辑层,各个窗口又有强引用,还时不时的带着绑定,看着实在是累啊.

楼猪一直醉心于MVVM模式,于是就想着怎么给改改.此处先郑重声明:我只是尽量用MVVM来实现和原作者相同的效果,界面素材均是直接从豆瓣电台照搬下来的.

果断的建个项目,拖prism,建模块,花了一天时间,居然都可以运行听歌了,实在是佩服我的敲代码速度.

先看下效果图:

左侧一共5个导航按钮,我准备对应到5个Module,各个Module处理自己的逻辑,简单明了.目前只实现了频道Module和最下面的关于我们Module.频道列表是从豆瓣服务器读取,选中1个频道会发出事件消息,主播放器接到这个事件消息会加载歌曲并自动开始播放,频道列表和主播放器是2个模块中的2个ViewModel,所以这个事件是通过EventAggregator传递.

右侧是主播放器,这里对应项目的一个核心Module,目前只是实现了播放,暂停,下一曲,调音量.这里比较恶心的是播放器进度条,MediaEelement的Position居然不是依赖属性,最后扔了个Timer监视.MediaElement加载歌曲的总时间也不是依赖属性,获取总时间时ViewModel强行访问了View上的控件,这里以后有时间再改过来.

大家注意李宗盛的头像,鼠标在主窗口移动会切换哦~这里是用Behavior注册了一大堆事件来实现的,其实和写在cs代码已经没多大区别了.这里的图片是跟正在播放的歌相关的,由于是2个ViewModel,也是用了EventAggregator通信.

部分切换使用了动画,动画的调用在样式里就可以定义,部分复杂的动画可以用Behavior或Trigger实现.播放器切换歌时,歌曲名称会有个动画,这里采用原作者的思路就必须访问Storyboard,由于ViewModel不应该关心这些页面资源,因此采用了Behavior来实现.

ViewModel打开子窗口,这里是定义了一个IWindow,通过在UnityContainer注册View实例来实现了ViewModel和View的解耦.ViewModel关闭View是可以在内部保持IView的引用,或者直接用InteractionRequest来实现,时间太晚了我实在是没力气写下去了.

解决方案的截图,看上去貌似比原版的复杂,不过界面上的每个大块都抽出来做成了Module,开发和调试神马的相当方便,我相信也没人愿意在2000行的CS代码中改代码吧.

项目采用了unity作为依赖注入容器.Client是程序主入口,只是作为一个Shell使用.项目核心是几大模块,分别加载的主窗口的各个区域,各自干各自的事,如果互相想摆会龙门阵神马的,就用EventAggregator通信.SmokeMusic.Common是模块共用层,里面放了很多资源,Converter,Behavior,Trigger,Dialog等等.Framework.Commo作为所有项目共用层,主要是放些Helper,扩展方法等等.Logic是逻辑层,主要是被模块调用,执行业务逻辑.

目前发现的不足:

1.部分控件很有用的属性不是依赖属性,这个是很杯具的.比如MediaElement的Position,FlowDocument的Document等等.遇到这时我们必须要么强行访问控件,要么就得写一大堆Behavior或Trigger来实现.

2.ViewModel之间暂时还没实现复用.其实MVVM的一大优点就是在解耦了逻辑和UI后,还能实现逻辑的复用性.

3.Module设计应该有缺陷.不知道怎么,就是感觉怪怪的.估计是设计能力还有很大缺陷,而且这个项目只是早上运行看了下效果,就开始写了,没有充分的考虑.

4.ViewModel如果在xaml构造,是没法依赖注入的.如果在cs文件构造并绑定,每个页面还得打开敲代码,远不如xaml中可以在设计器一键搞定,而且设计器不会即时产生绑定效果.这个真心无解啊.

最后还是放上源码,有砖请轻拍!所以引用类库均在解决方案根目录,using文件夹下.项目采用VS2012,.net4.0开发,推荐用VS2010 SP1,VS2012打开.

源码下载

 
分类: WPF

上一个版本 是利用周日休息时间制作的,考虑不充分,开发时间也短,只完成了加载频道列表和播放歌曲的功能.这几天晚上在家进行了部分加工,首先是完善了部分功能,其次对部分不合理的设计进行了重构(还不知道重构得合理不合理).

首先看下部分功能截图:

首先是搜索功能完成了部分.点击搜索功能会切换到该频道,并加载歌曲放歌.设计时,就把搜索做成了一个模块,频道是一个模块,播放器是一个模块.选中搜索结果,会由搜索模块发出事件消息.频道模块根据选中的搜索结果构造合适的频道,并发出事件通知播放器.播放器根据当前频道再加载歌曲.

这样子设计的好处是,模块只需要关心自己的业务逻辑,方便维护.比如,所有对频道的操作都是在频道模块内,所有对歌曲的操作都是在播放器模块,不会造成逻辑混乱.

其次就是左侧的导航,以前是在页面写了5个Region,这样很傻的,现在是通过把模块注册到TabControl的方式来实现.这样更好方便管理.

有个小功能,在不同的歌曲时,会根据封面图片切换背景色.设计时把封面做成了一个模块,封面模块会监听切换歌曲的事件,并下载图片.图片下载完毕后,通知主界面更换背景色.

这里更可以看到,在ViewModel通过调用InteractionRequest或者其他的方式来操作动画是没有任何问题的.

弹出的子窗口,也会跟着主窗口变色,这个用个绑定就实现了.程序里定义了一个ChildWindowViewModelBase类,专门处理弹出窗口,在ViewModel内部可以实现窗口的打开关闭等常用功能.

这里的窗口打开后,对应按钮是灰掉的.只需要保证按钮和窗口的DataContext是同一个ViewModel,再利用一个IsOpen的属性就很好实现了.如果用事件驱动,就不得不注册一堆事件来实现这个功能,这也体现了MVVM把UI和逻辑分开的优势.

应用程序内置了一个捕捉异常的模块,这里是通过应用程序发起一个出错的事件消息,ExceptionViewModel捕捉到后记录日志,打开提示框.

现在的项目采用了大量的事件消息.比如:所有模块加载完毕会发出一个事件消息,Channel模块捕捉到后会开始加载频道,Account模块会开始尝试自动登录等等.应用程序退出会发出一个事件消息,右下角气泡(Notify模块)会释放资源.

合理的采用事件(EventAggregator)会避免模块之间的强引用,实现解耦.

现在的解决方案已经颇具规模了.接下来可能再加入一个歌词模块,然后就不会有新的模块了.

这里得说下分这么多模块的好处:

首先,按照上面说的,把业务逻辑分到不同的模块,方便维护.如果是团队开发,那么把模块分给不同的开发人员,互相的开发工作也不会受到影响.

其次,模块可以实现按需加载.目前项目中模块是全部加载的,我们可以做个适当的判断,只加载其中部分.最关键的是,由于模块之间没有强引用,缺少部分模块对应用程序不会产生任何影响!可能你只是不能搜索,或者不能登录,或者不能放歌,但是应用程序会正常运行,而且其他模块的操作都可以正常进行.

第三,可以随时建立模块来替换以前的模块.同上所述,这样的替换操作不会对应用程序带来任何影响.

目前很多功能都不完善,我会慢慢的把功能都补上,并尝试加点自己觉得有用的东西.当然,所有的代码都是以Prism为框架,MVVM模式为指导思想.

最后还是放上源码.

注意:此项目UI和部分逻辑参考了开源的音乐播放器 豆瓣电台 ,请大家只用来做学习和拍砖楼猪的武器就行了.

再注意:项目采用VS2012开发,VS2012SP1能顺利打开.

源码下载

 
分类: WPF
原文地址:https://www.cnblogs.com/Leo_wl/p/2750909.html