對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打開.