估計大家看到這個標題,可能還無法理解我這個系統是用來干什么的,先說一個場景,猶如一些咖啡廳的心語牆,客戶可以找服務員索取便簽紙,寫下自己的心語,然后在心語牆上找一個合適的位置貼下。對於這個便簽紙,自己在將來的某一天再次光顧這家咖啡廳還可以看到自己以前貼下的心語。當然,其他的顧客也可以瀏覽,說了這么多,如果您感興趣,可以猛擊:http://fendouzl.s2.jutuo.net 。如果不登錄,還有很多功能看不到哦。不過由於時間有限,又要工作,又要做這個畢設系統,還得寫論文,因此,目前這個系統還是比較粗糙的,有時間我會去完善之,因為這個系統是我自己在生活中覺得的確需要,正好以前學了silverlight,便想把這個生活模型使用silverlight來模擬,盡管模擬的不好,大家不要見笑,可以直接給我留言指正,我會加以改正的哈。
下面先看看其中一個功能模塊的截圖
作為一個技術性文章,還是來說說本系統技術方便的事情,不然真會被其他的同學說我在這打廣告了。
1 系統架構設計
首先,我想說的是系統的架構,個人覺得這個做一個系統的時候,最好有一個架構圖,有了這個架構圖,便可以通過這個圖導出一個合理的解決方案以及解決方案里面的項目,之后的工作便是在各個項目中填充代碼,相對來說還是比較容易的。
1.1 服務器端架構設計
服務器端架構設計的出發點便是如何高效快捷的訪問數據庫。如圖下圖所示,可以看到本系統服務端分為四層和三個輔助性的類庫,分別是業務邏輯層、工廠層、數據鏈路接口層、數據鏈路層、數據訪問工具層、公共層、數據庫模板層。客戶端通過WCF訪問業務邏輯層的方法,由於業務邏輯層繼承工廠層,因此這個工廠層通過反射技術,動態加載數據鏈路層的方法,並且輔助層的配合下完成數據庫讀寫,最后把結果通過JSON序列化之后返回給客戶端。
1.2 客戶端架構設計
客戶端主要是silverlight的實現,為了提高客戶端代碼的重構性和易移植性,決定在客戶端使用MVVM模式,架構圖如圖28所示。其中View層便是UI界面的實現,Model層便是數據源,而ViewModel層便是為了讓數據在View層顯示的中介。客戶端通過WCF請求數據,服務端把數據通過JSON序列化之后返回給客戶端。
2.系統解決方案圖
通過系統架構圖,可以很容易的映射出系統解決方案,系統解決方案列表圖如下圖所示。目前,自己的技術還不怎么好,不過大型項目,為了避免邏輯混亂,是有必要去分層實現,使用必要的模式,如我這個客戶端使用MVVM模式,服務器分為四層。
3 如何連接silverlight客戶端上和服務器端
對於這個問題,大家一般都會只用WCF,當然,我也選擇這個方式,因為相對比較容易,並且很方便。

public void Get**FromDB() { string query = “condition” Proxy.GetListAsync(JsonConvert.SerializeObject(query)); Proxy.GetListCompleted += new EventHandler<UserOwnWallServiceReference.GetListCompletedEventArgs>(Proxy_GetListCompleted); } } void Proxy_GetListCompleted(object sender, UserOwnWallServiceReference.GetListCompletedEventArgs e) { Deployment.Current.Dispatcher.BeginInvoke(delegate { if (e.Error == null) { _UserOwnWallCollection = JsonConvert.DeserializeObject<ObservableCollection<UserOwnWall>>(e.Result.ToString()); InitUserUI(); } }); }}
這段代碼大致展示了用戶如何使用WCF服務代理契約去訪問遠程數據,至於如何去編寫這個服務契約,使用是需要注意什么問題,我就不詳細講了,因為在使用的時候的確會遇到各種奇奇怪怪的問題,不過主要應該是配置文件的改動。
4 用戶控件移動代碼詳解
大家如何查看了http://fendouzl.s2.jutuo.net,那么就應該知道,系統很多地方用到了便簽紙在Canvas上移動的體驗,為此,我寫了一個類來管理便簽紙移動,其實就是一個用戶的控件在canvas上移動,代碼如下:

1 public class MouseMoveHelper 2 { 3 #region move 4 static Point _curPoint; //當前點 5 static bool _mouseMoving = false; //定義是否移動中的布爾變量 6 public static void MouseButtonUpHandler(object sender, MouseButtonEventArgs e) 7 { 8 FrameworkElement element = sender as FrameworkElement; 9 element.SetValue(CustomCanvasControl.ZIndexProperty, 0); 10 //放開鼠標之后修改變量值 11 _mouseMoving = false; 12 //停止捕捉鼠標位置 13 element.ReleaseMouseCapture(); 14 //設置當期X Y坐標為0 15 _curPoint.X = 0; 16 _curPoint.Y = 0; 17 //恢復鼠標指針樣式 18 element.Cursor = null; 19 } 20 21 public static void MouseButtonDownHandler(object sender, MouseButtonEventArgs e) 22 { 23 FrameworkElement element = sender as FrameworkElement; 24 element.SetValue(CustomCanvasControl.ZIndexProperty, 1); 25 //獲得當前鼠標的位置 26 _curPoint = e.GetPosition(element.Parent as CustomCanvasControl); 27 //設置開始拖動的值 28 _mouseMoving = true; 29 if (null != element) { 30 //捕捉鼠標位置 31 element.CaptureMouse(); 32 element.Cursor = Cursors.Hand; 33 } 34 } 35 36 public static void MouseMoveHandler(object sender, MouseEventArgs e) 37 { 38 FrameworkElement element = sender as FrameworkElement; 39 if (_mouseMoving) { 40 try { 41 double currX = e.GetPosition(element.Parent as CustomCanvasControl).X - _curPoint.X; 42 double currY = e.GetPosition(element.Parent as CustomCanvasControl).Y - _curPoint.Y; 43 44 //得到當前畫布的寬度和高度 45 double currCanvasWidth = (element.Parent as Canvas).ActualWidth; 46 double currCanvasHeight = (element.Parent as Canvas).ActualHeight; 47 48 //得到當前移動目標的寬度高度 49 double currElementWidth = element.ActualWidth; 50 double currElementHeight = element.ActualHeight; 51 52 if ((currY + (double)element.GetValue(CustomCanvasControl.TopProperty) < 0) || 53 (currX + (double)element.GetValue(CustomCanvasControl.LeftProperty) < 0) 54 || (currY + (double)element.GetValue(CustomCanvasControl.TopProperty) > currCanvasHeight - currElementHeight) || 55 (currX + (double)element.GetValue(CustomCanvasControl.LeftProperty) > currCanvasWidth - currElementWidth)) { 56 //不作任務操作,不移動 57 } else { 58 59 //設置對象坐標 60 element.SetValue(CustomCanvasControl.TopProperty, currY + (double)element.GetValue(CustomCanvasControl.TopProperty)); 61 element.SetValue(CustomCanvasControl.LeftProperty, currX + (double)element.GetValue(CustomCanvasControl.LeftProperty)); 62 } 63 } catch { 64 } 65 } 66 //保存當前坐標值 67 _curPoint = e.GetPosition(element.Parent as CustomCanvasControl); 68 } 69 70 #endregion 71 }
5 Json序列化
目前用來保存和傳遞數據一般使用Json和XML.使用這兩個技術,相對比較容易,重要的很多平台都使用這個兩中方式,因此比較通過,Json的使用方式基本是就是序列化和反序列化,使用比較多的是以下兩個方法:

JsonConvert.SerializeObject()
JsonConvert.DeserializeObject<>()
6 HTML 5 GelLocation API
因為系統需要定位,因為使用了HTML 5 的定位API,這個相對來說還是比較容易的,就是一個API,自己的去調用就行,還是給出代碼:

1 function getUserLocation() { 2 if (navigator.geolocation) { 3 navigator.geolocation.getCurrentPosition(show_map); 4 } else { 5 alert("您的瀏覽器不支持HTML 5來獲取地理位置信息。"); 6 } 7 } 8 function show_map(position) { 9 var latitude = position.coords.latitude; 10 var longitude = position.coords.longitude; 11 callSL(latitude, longitude); 12 } 13 14 function callSL(latitude, longitude) { 15 var slHost = document.getElementById("SilverlightControl"); 16 var page = slHost.Content.FootprintContainer; 17 slHost.Content.FootprintContainer.Process(longitude, latitude); 18 }
需要注意的是,Silverlight如何與javascript通信,代碼中也有體現,如何大家感興趣還是去查看相關資料,
7 早來的總結
這個總結的確來的比較早吧,因為還有一些用到的技術還沒有來得及寫,好不容易一個假期,我卻需要來寫畢設,馬上又得去上班,因此的確沒有更多的時間,再加上自己的確還有很多說不明白講不清楚。不得不說一個人想將來過的好一點,年輕的時候就需要去拼搏。對於前面我講的,相信大家也注意到了,我對代碼的細節沒有做更多的講解,因為現在網上資源還是比較豐富的,只要大家知道有這么回事,知道關鍵詞,便可以很容易的找到答案,因此我寫的這篇文章的重點不是在說具體代碼是如何實現的,而是提到一個個知識點,一條條思路。說到這兒,相信大蝦開始笑了,不過我還是想說說,成為大蝦是一個過程,而不是一個結果。