在Winform開發中,客戶體驗是個很好的參考性指標,如果一個功能使用的時候感覺很流暢,說明我們的程序執行效率還不錯,但是隨着數據的真多,原先可能流程的地方可能會變得比較卡,這時候就需要追本索源,找到症結並進行處理。但是,如果我們對Winform開發有一定的經驗積累,有些耗時緩慢的界面處理一開始還是比較容易避免,本文介紹一些在開發過程中的一些界面性能上的優化處理,希望對大家有幫助。
1、案例說明
在我開發的CRM系統中,系統的一些用戶如經辦人員,來自權限管理系統,因此在開發的時候,並沒有模擬太多的用戶,因此,開始的設計處理是通過下拉列表列出相關的用戶即可,如下所示。

最開始的考慮是讓用戶能夠快速選擇所需要的經辦人員,默認是當前用戶,這種設計開始不會有任何問題,因為數據少,測試起來非常流暢。
插入用戶的界面部分是這樣處理的,由於這個經辦人是很多界面地方用到的,所以把它封裝為一個界面控件,需要的地方拖過去使用即可,和普通的文本框一樣的使用方法。

上面的控件初始化的時候,應該列出一些用戶信息,如下所示。
List<UserInfo> userList = BLLFactory<User>.Instance.GetAll(); foreach (SimpleUserInfo info in userList) { this.txtOperator.Properties.Items.Add(new CListItem(info.FullName, info.ID.ToString())); }
2、界面效率優化
1)優化一
上面的代碼粗看沒有什么問題,但是我們知道,下拉列表為了提高效率,一般有一個BeginUpdate,EndUpdate的方法用來實現批量錄入。為了提高速度,這點我們需要利用上,然后代碼就修改為下面的處理方式。
this.txtOperator.Properties.BeginUpdate(); List<UserInfo> userList = BLLFactory<User>.Instance.GetAll(); foreach (SimpleUserInfo info in userList) { this.txtOperator.Properties.Items.Add(new CListItem(info.FullName, info.ID.ToString())); } this.txtOperator.Properties.EndUpdate();
在數據不算很多的時候,感覺速度比原來卻是快了一些。
2)優化二
但是發現我的權限系統用戶數據增加到幾百個的人員的時候,速度就有點卡了。問題出現在哪里?
由於權限管理系統中用戶表是一個較為龐大的表,如下所示。

每次獲取用戶的時候,我們調用了下面的代碼。
BLLFactory<User>.Instance.GetAll()
這個操作是把用戶的全部信息字段都獲取一次,速度肯定比較慢了,那么我們來改進一下,因為我們這里控件只需要綁定一些簡單的用戶名,用戶ID,用戶姓名等基礎字段,我們來簡化一個對象用來實現數據的獲取,如下所示。
於是我在權限管理系統定義了一個簡單的用戶對象,稱為SimpleUserInfo,它只是包含了幾個基本的字段即可,這樣綁定代碼修改如下。
this.txtOperator.Properties.BeginUpdate(); this.txtOperator.Properties.Items.Clear(); List<SimpleUserInfo> userList = BLLFactory<User>.Instance.GetSimpleUsers(); foreach (SimpleUserInfo info in userList) { this.txtOperator.Properties.Items.Add(new CListItem(info.FullName, info.ID.ToString())); } this.txtOperator.Properties.EndUpdate();
好了,速度很快了,一眨眼功夫,幾百個用戶都列出來了,非常高興。
3)優化三
上面確實感覺速度飛快了,幾百個用戶瞬間加載,解決了速度的問題,但是帶來了另外一個問題,幾百個用戶,我們通過列表選擇用戶是否太費眼力了呢,一個個找,沒有查找過濾?好費勁!
好既然速度提上來了,我們改進一下用戶體驗的效果吧,好像記得DevExpress有一個查找的下拉列表叫做SearchLookupEdit,就用它了。
先另外定義一個基於SearchLookupEdit的界面控件,如下所示。

設置它里面列表需要顯示的字段,如下所示。

綁定代碼如下所示。
private void OperatorSelectControl_Load(object sender, EventArgs e) { if (!this.DesignMode) { txtOperator.Properties.ValueMember = "ID"; txtOperator.Properties.DisplayMember = "FullName"; txtOperator.Properties.DataSource = BLLFactory<User>.Instance.GetSimpleUsers(); } }
上面的設計和代碼綁定弄完成后,我們來看看具體的效果了。

通過彈出的GridView里面展示用戶信息,並能支持查詢搜索,選擇用戶速度快了很多,同時也提高用戶體驗。
4)優化四
說完了優化三,看到優化四,是不是心里說道,不是吧,還有更好的?
當然,我們知道Winform里面很多時候,數據可能都會被反復使用,如經辦人員,一般來說,很多界面可能都需要,那么每次都需要從數據庫里面取出幾百個用戶,效率上感覺還是不太好,特別如果是在我的混合式框架中用到的WCF的分布式獲取數據方式,也就是說數據不再本地,需要通過網絡方式獲取,那么就會產生帶寬的問題,效率可能無法保證。
好了,說到這里,就是指我想把這些常用到,不會經常變化的數據緩存起來,供下一步繼續使用。
我們看看獲取用戶數據的地方修改為下面的方法,關於MemoryCacheHelper的定義及說明,可以參考我上一篇介紹WInform里面使用緩存的隨筆《Winform里面的緩存使用》。
/// <summary> /// 獲取用戶全部簡單對象信息,並放到緩存里面 /// </summary> /// <returns></returns> public static List<SimpleUserInfo> GetSimpleUsers() { System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); string key = string.Format("{0}-{1}", method.DeclaringType.FullName, method.Name); return MemoryCacheHelper.GetCacheItem<List<SimpleUserInfo>>(key, delegate() { return BLLFactory<User>.Instance.GetSimpleUsers(); }, new TimeSpan(0, 10, 0));//10分鍾過期 }
好了,使用緩存獲取數據,我們只需要稍微調整下控件的獲取數據代碼即可,如下所示。
private void OperatorSelectControl_Load(object sender, EventArgs e) { if (!this.DesignMode) { txtOperator.Properties.ValueMember = "ID"; txtOperator.Properties.DisplayMember = "FullName"; txtOperator.Properties.DataSource = SecurityHelper.GetSimpleUsers(); } }
以上經驗就是在我的《CRM客戶關系管理系統》里面,對於經辦人這樣的用戶選擇界面所做的一步步精益求精的優化嘗試和歷程,希望給大家在做同樣操作的時候常考。
如果有興趣,可以進一步了解這個系統的各種界面設計效果。
