对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打开.

源码下载

posted on 2012-10-28 23:51  烟灰灰  阅读(9205)  评论(34编辑  收藏  举报